home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Science⁄Math / Gnuplot 3.5 for Macintosh / SOURCES 3.5 / graph3d_2.c < prev    next >
Text File  |  1993-11-12  |  87KB  |  3,122 lines

  1. #ifndef lint
  2. static char *RCSid = "$Id: graph3d.c%v 3.50.1.9 1993/08/05 05:38:59 woo Exp $";
  3. #endif
  4.  
  5.  
  6. /* GNUPLOT - graph3d.c */
  7. /*
  8.  * Copyright (C) 1986 - 1993   Thomas Williams, Colin Kelley
  9.  *
  10.  * Permission to use, copy, and distribute this software and its
  11.  * documentation for any purpose with or without fee is hereby granted, 
  12.  * provided that the above copyright notice appear in all copies and 
  13.  * that both that copyright notice and this permission notice appear 
  14.  * in supporting documentation.
  15.  *
  16.  * Permission to modify the software is granted, but not the right to
  17.  * distribute the modified code.  Modifications are to be distributed 
  18.  * as patches to released version.
  19.  *
  20.  * This software is provided "as is" without express or implied warranty.
  21.  *
  22.  *
  23.  * AUTHORS
  24.  *
  25.  *   Original Software:
  26.  *       Gershon Elber and many others.
  27.  *
  28.  * 19 September 1992  Lawrence Crowl  (crowl@cs.orst.edu)
  29.  * Added user-specified bases for log scaling.
  30.  *
  31.  * There is a mailing list for gnuplot users. Note, however, that the
  32.  * newsgroup 
  33.  *    comp.graphics.gnuplot 
  34.  * is identical to the mailing list (they
  35.  * both carry the same set of messages). We prefer that you read the
  36.  * messages through that newsgroup, to subscribing to the mailing list.
  37.  * (If you can read that newsgroup, and are already on the mailing list,
  38.  * please send a message info-gnuplot-request@dartmouth.edu, asking to be
  39.  * removed from the mailing list.)
  40.  *
  41.  * The address for mailing to list members is
  42.  *       info-gnuplot@dartmouth.edu
  43.  * and for mailing administrative requests is 
  44.  *       info-gnuplot-request@dartmouth.edu
  45.  * The mailing list for bug reports is 
  46.  *       bug-gnuplot@dartmouth.edu
  47.  * The list of those interested in beta-test versions is
  48.  *       info-gnuplot-beta@dartmouth.edu
  49.  */
  50.  
  51. #include <stdio.h>
  52. #include <math.h>
  53. #include <assert.h>
  54. #if !defined(u3b2)
  55. #include <time.h>
  56. #endif
  57. #if !defined(sequent) && !defined(apollo) && !defined(alliant)
  58. #include <limits.h>
  59. #endif
  60. #include "plot.h"
  61. #ifdef THINK_C
  62. #include "tout_protos.h"
  63. #endif
  64. #include "setshow.h"
  65.  
  66. #if defined(DJGPP)||defined(sun386)
  67. #define time_t unsigned long
  68. #endif
  69.  
  70. #if defined(apollo) || defined(sequent) || defined(u3b2) || defined(alliant) || defined(sun386)
  71. #include <sys/types.h> /* typedef long time_t; */
  72. #endif
  73.  
  74. #ifdef THINK_C
  75. #define THINK_C_4
  76. #endif
  77.  
  78.  
  79.  
  80. #if defined(THINK_C_3)
  81. int suppressMove = 0;  /* for preventing moveto while drawing contours */
  82. #elif defined(THINK_C_4)
  83. extern int suppressMove;  /* for preventing moveto while drawing contours */
  84. #else
  85. int suppressMove = 0;  /* for preventing moveto while drawing contours */
  86. #endif
  87.  
  88. #ifndef AMIGA_SC_6_1
  89. extern char *strcpy(),*strncpy(),*strcat(),*ctime(),*tdate;
  90. #else /* AMIGA_SC_6_1 */
  91. extern char *tdate;
  92. #endif /* AMIGA_SC_6_1 */
  93. #ifdef AMIGA_AC_5
  94. extern time_t dated;
  95. #else
  96. extern time_t dated; /* ,time(); */
  97. #include <time.h>
  98. #endif
  99.  
  100. #ifdef __TURBOC__
  101. #include <stdlib.h>        /* for qsort */
  102. #endif
  103.  
  104. /*
  105.  * hidden_line_type_above, hidden_line_type_below - controls type of lines
  106.  *   for above and below parts of the surface.
  107.  * hidden_no_update - if TRUE lines will be hidden line removed but they
  108.  *   are not assumed to be part of the surface (i.e. grid) and therefore
  109.  *   do not influence the hidings.
  110.  * hidden_active - TRUE if hidden lines are to be removed.
  111.  */
  112. #if defined(THINK_C_3)
  113. int hidden_active = FALSE;
  114. #elif defined(THINK_C_4)
  115. extern int hidden_active;
  116. #else
  117. static int hidden_active = FALSE;
  118. #endif
  119.  
  120. /* LITE defines a restricted memory version for MS-DOS */
  121.  
  122. #ifndef LITE
  123.  
  124. #if defined(THINK_C_3)
  125. int hidden_line_type_above, hidden_line_type_below, hidden_no_update;
  126. #elif defined(THINK_C_4)
  127. extern int hidden_line_type_above, hidden_line_type_below, hidden_no_update;
  128. #else
  129. static int hidden_line_type_above, hidden_line_type_below, hidden_no_update;
  130. #endif
  131.  
  132. /* We divvy up the figure into the component boxes that make it up, and then
  133.    sort them by the z-value (which is really just an average value).  */
  134. struct pnts{
  135.   int x,y,z;
  136.   int flag;
  137.   long int style_used;    /* acw test */
  138.   int nplot;
  139. };
  140.  
  141. #if defined(THINK_C_3)
  142. int * boxlist;
  143. struct pnts * nodes;
  144. #elif defined(THINK_C_4)
  145. extern int * boxlist;
  146. extern struct pnts * nodes;
  147. #else
  148. static int * boxlist;
  149. static struct pnts * nodes;
  150. #endif
  151.  
  152. /* These variables are used to keep track of the range of x values used in the
  153. line drawing routine.  */
  154. #if defined(THINK_C_3)
  155. long int xmin_hl,xmax_hl;
  156. #elif defined(THINK_C_4)
  157. extern long int xmin_hl,xmax_hl;
  158. #else
  159. static long int xmin_hl,xmax_hl;
  160. #endif
  161.  
  162. /* These arrays are used to keep track of the minimum and maximum y values used
  163.    for each X value.  These are only used for drawing the individual boxes that
  164.    make up the 3d figure.  After each box is drawn, the information is copied
  165.    to the bitmap. */
  166. #if defined(THINK_C_3)
  167. short int *ymin_hl, *ymax_hl;
  168. #elif defined(THINK_C_4)
  169. extern short int *ymin_hl, *ymax_hl;
  170. #else
  171. static short int *ymin_hl, *ymax_hl;
  172. #endif
  173.  
  174. /*
  175.  * These numbers are chosen as dividers into the bitmap.
  176.  */
  177. #if defined(THINK_C_3)
  178. short int xfact, yfact;
  179. #elif defined(THINK_C_4)
  180. extern short int xfact, yfact;
  181. #else
  182. static short int xfact, yfact;
  183. #endif
  184.  
  185. #define XREDUCE(X) ((X)/xfact)
  186. #define YREDUCE(Y) ((Y)/yfact)
  187.  
  188. /* Bitmap of the screen.  The array for each x value is malloc-ed as needed */
  189. #if defined(THINK_C_3)
  190. short int **pnt;
  191. #elif defined(THINK_C_4)
  192. extern short int **pnt;
  193. #else
  194. static short int **pnt;
  195. #endif
  196.  
  197. #define IFSET(X,Y) (pnt[X] == 0 ? 0 : (((pnt[X])[(Y)>>4] >> ((Y) & 0xf)) & 0x01))
  198.  
  199. #if defined(THINK_C_3)
  200. int plot3d_hidden();
  201. #elif defined(THINK_C_4)
  202. extern int plot3d_hidden();
  203. #else
  204. static int plot3d_hidden();
  205. #endif
  206.  
  207. #endif /* LITE */
  208.  
  209.  
  210.  
  211.  
  212.  
  213. #if defined(THINK_C_3)
  214. static plot3d_impulses();
  215. static plot3d_lines();
  216. static plot3d_points();
  217. static plot3d_dots();
  218. static cntr3d_impulses();
  219. static cntr3d_lines();
  220. static cntr3d_points();
  221. static cntr3d_dots();
  222. int update_extrema_pts();
  223. int setlinestyle();
  224. extern int xtick3d();
  225. extern int ytick3d();
  226. extern int ztick3d();
  227. #elif defined(THINK_C_4)
  228. static draw_parametric_grid();
  229. static draw_non_param_grid();
  230. int draw_bottom_grid();
  231. static draw_3dxtics();
  232. static draw_3dytics();
  233. static draw_3dztics();
  234. static draw_series_3dxtics();
  235. static draw_series_3dytics();
  236. static draw_series_3dztics();
  237. static draw_set_3dxtics();
  238. static draw_set_3dytics();
  239. static draw_set_3dztics();
  240. int xtick3d();
  241. int ytick3d();
  242. int ztick3d();
  243. #else
  244. static plot3d_impulses();
  245. static plot3d_lines();
  246. static plot3d_points();
  247. static plot3d_dots();
  248. static cntr3d_impulses();
  249. static cntr3d_lines();
  250. static cntr3d_points();
  251. static cntr3d_dots();
  252. static update_extrema_pts();
  253. static setlinestyle();
  254. static draw_parametric_grid();
  255. static draw_non_param_grid();
  256. static draw_bottom_grid();
  257. static draw_3dxtics();
  258. static draw_3dytics();
  259. static draw_3dztics();
  260. static draw_series_3dxtics();
  261. static draw_series_3dytics();
  262. static draw_series_3dztics();
  263. static draw_set_3dxtics();
  264. static draw_set_3dytics();
  265. static draw_set_3dztics();
  266. static xtick();
  267. static ytick();
  268. static ztick();
  269. #endif
  270.  
  271. #ifdef __PUREC__
  272. /* a little problem with the 16bit int size of PureC. this completely broke
  273.    the hidded3d feature. doesn't really fix it, but I'm working at it.  (AL) */
  274. static int clip_point(int x, int y);
  275. static void clip_put_text(int x, int y, char *str);
  276. #endif
  277.  
  278. #ifndef max        /* Lattice C has max() in math.h, but shouldn't! */
  279. #define max(a,b) ((a > b) ? a : b)
  280. #endif
  281.  
  282. #ifndef min
  283. #define min(a,b) ((a < b) ? a : b)
  284. #endif
  285.  
  286. #define inrange(z,min,max) ((min<max) ? ((z>=min)&&(z<=max)) : ((z>=max)&&(z<=min)) )
  287.  
  288. #define apx_eq(x,y) (fabs(x-y) < 0.001)
  289. #ifndef abs
  290. #define abs(x) ((x) >= 0 ? (x) : -(x))
  291. #endif
  292. #define sqr(x) ((x) * (x))
  293.  
  294. /* Define the boundary of the plot
  295.  * These are computed at each call to do_plot, and are constant over
  296.  * the period of one do_plot. They actually only change when the term
  297.  * type changes and when the 'set size' factors change. 
  298.  */
  299. #if defined(THINK_C_3)
  300. int xleft, xright, ybot, ytop, xmiddle, ymiddle, xscaler, yscaler;
  301. #elif defined(THINK_C_4)
  302. extern int xleft, xright, ybot, ytop, xmiddle, ymiddle, xscaler, yscaler;
  303. #else
  304. static int xleft, xright, ybot, ytop, xmiddle, ymiddle, xscaler, yscaler;
  305. #endif
  306.  
  307. /* Boundary and scale factors, in user coordinates */
  308. /* x_min3d, x_max3d, y_min3d, y_max3d, z_min3d, z_max3d are local to this
  309.  * file and are not the same as variables of the same names in other files
  310.  */
  311. #if defined(THINK_C_3)
  312. double x_min3d, x_max3d, y_min3d, y_max3d, z_min3d, z_max3d;
  313. double xscale3d, yscale3d, zscale3d;
  314. double real_z_min3d, real_z_max3d;
  315. double min_sy_ox,min_sy_oy; /* obj. coords. for xy tics placement. */
  316. double min_sx_ox,min_sx_oy; /* obj. coords. for z tics placement. */
  317. #elif defined(THINK_C_4)
  318. extern double x_min3d, x_max3d, y_min3d, y_max3d, z_min3d, z_max3d;
  319. extern double xscale3d, yscale3d, zscale3d;
  320. extern double real_z_min3d, real_z_max3d;
  321. extern double min_sy_ox,min_sy_oy; /* obj. coords. for xy tics placement. */
  322. extern double min_sx_ox,min_sx_oy; /* obj. coords. for z tics placement. */
  323. #else
  324. static double x_min3d, x_max3d, y_min3d, y_max3d, z_min3d, z_max3d;
  325. static double xscale3d, yscale3d, zscale3d;
  326. static double real_z_min3d, real_z_max3d;
  327. static double min_sy_ox,min_sy_oy; /* obj. coords. for xy tics placement. */
  328. static double min_sx_ox,min_sx_oy; /* obj. coords. for z tics placement. */
  329. #endif
  330.  
  331. #ifndef THINK_C
  332. typedef double transform_matrix[4][4];
  333. #endif
  334.  
  335. #if defined(THINK_C_3)
  336. transform_matrix trans_mat;
  337. #elif defined(THINK_C_4)
  338. extern transform_matrix trans_mat;
  339. #else
  340. static transform_matrix trans_mat;
  341. #endif
  342.  
  343.  
  344. /* (DFK) Watch for cancellation error near zero on axes labels */
  345. #define SIGNIF (0.01)        /* less than one hundredth of a tic mark */
  346. #define CheckZero(x,tic) (fabs(x) < ((tic) * SIGNIF) ? 0.0 : (x))
  347. #define NearlyEqual(x,y,tic) (fabs((x)-(y)) < ((tic) * SIGNIF))
  348.  
  349. /* And the functions to map from user to terminal coordinates */
  350. #define map_x(x) (int)(x+0.5) /* maps floating point x to screen */ 
  351. #define map_y(y) (int)(y+0.5)    /* same for y */
  352.  
  353. /* And the functions to map from user 3D space into normalized -1..1 */
  354. #define map_x3d(x) ((x-x_min3d)*xscale3d-1.0)
  355. #define map_y3d(y) ((y-y_min3d)*yscale3d-1.0)
  356. #define map_z3d(z) ((z-z_min3d)*zscale3d-1.0)
  357.  
  358.  
  359. #if defined(THINK_C_4)
  360.  
  361. static mat_unit(mat)
  362. transform_matrix mat;
  363. {
  364.     int i, j;
  365.  
  366.     for (i = 0; i < 4; i++) for (j = 0; j < 4; j++)
  367.     if (i == j)
  368.         mat[i][j] = 1.0;
  369.     else
  370.         mat[i][j] = 0.0;
  371. }
  372.  
  373. static mat_trans(tx, ty, tz, mat)
  374. double tx, ty, tz;
  375. transform_matrix mat;
  376. {
  377.      mat_unit(mat);                                 /* Make it unit matrix. */
  378.      mat[3][0] = tx;
  379.      mat[3][1] = ty;
  380.      mat[3][2] = tz;
  381. }
  382.  
  383. #ifdef THINK_C
  384. mat_scale(sx, sy, sz, mat)
  385. #else
  386. static mat_scale(sx, sy, sz, mat)
  387. #endif
  388. double sx, sy, sz;
  389. transform_matrix mat;
  390. {
  391.      mat_unit(mat);                                 /* Make it unit matrix. */
  392.      mat[0][0] = sx;
  393.      mat[1][1] = sy;
  394.      mat[2][2] = sz;
  395. }
  396.  
  397. #ifdef THINK_C
  398. mat_rot_x(teta, mat)
  399. #else
  400. static mat_rot_x(teta, mat)
  401. #endif
  402. double teta;
  403. transform_matrix mat;
  404. {
  405.     double cos_teta, sin_teta;
  406.  
  407.     teta *= Pi / 180.0;
  408.     cos_teta = cos(teta);
  409.     sin_teta = sin(teta);
  410.  
  411.     mat_unit(mat);                                  /* Make it unit matrix. */
  412.     mat[1][1] = cos_teta;
  413.     mat[1][2] = -sin_teta;
  414.     mat[2][1] = sin_teta;
  415.     mat[2][2] = cos_teta;
  416. }
  417.  
  418. static mat_rot_y(teta, mat)
  419. double teta;
  420. transform_matrix mat;
  421. {
  422.     double cos_teta, sin_teta;
  423.  
  424.     teta *= Pi / 180.0;
  425.     cos_teta = cos(teta);
  426.     sin_teta = sin(teta);
  427.  
  428.     mat_unit(mat);                                  /* Make it unit matrix. */
  429.     mat[0][0] = cos_teta;
  430.     mat[0][2] = -sin_teta;
  431.     mat[2][0] = sin_teta;
  432.     mat[2][2] = cos_teta;
  433. }
  434.  
  435. #ifdef THINK_C
  436. mat_rot_z(teta, mat)
  437. #else
  438. static mat_rot_z(teta, mat)
  439. #endif
  440. double teta;
  441. transform_matrix mat;
  442. {
  443.     double cos_teta, sin_teta;
  444.  
  445.     teta *= Pi / 180.0;
  446.     cos_teta = cos(teta);
  447.     sin_teta = sin(teta);
  448.  
  449.     mat_unit(mat);                                  /* Make it unit matrix. */
  450.     mat[0][0] = cos_teta;
  451.     mat[0][1] = -sin_teta;
  452.     mat[1][0] = sin_teta;
  453.     mat[1][1] = cos_teta;
  454. }
  455.  
  456. /* Multiply two transform_matrix. Result can be one of two operands. */
  457. void mat_mult(mat_res, mat1, mat2)
  458. transform_matrix mat_res, mat1, mat2;
  459. {
  460.     int i, j, k;
  461.     transform_matrix mat_res_temp;
  462.  
  463.     for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) {
  464.         mat_res_temp[i][j] = 0;
  465.         for (k = 0; k < 4; k++) mat_res_temp[i][j] += mat1[i][k] * mat2[k][j];
  466.     }
  467.     for (i = 0; i < 4; i++) for (j = 0; j < 4; j++)
  468.     mat_res[i][j] = mat_res_temp[i][j];
  469. }
  470.  
  471. /* And the functions to map from user 3D space to terminal coordinates */
  472. #ifdef THINK_C
  473. int map3d_xy(x, y, z, xt, yt)
  474. #else
  475. static int map3d_xy(x, y, z, xt, yt)
  476. #endif
  477. double x, y, z;
  478. int *xt, *yt;
  479. {
  480.     int i,j;
  481.     double v[4], res[4],             /* Homogeneous coords. vectors. */
  482.     w = trans_mat[3][3];
  483.  
  484.     v[0] = map_x3d(x); /* Normalize object space to -1..1 */
  485.     v[1] = map_y3d(y);
  486.     v[2] = map_z3d(z);
  487.     v[3] = 1.0;
  488.  
  489.     for (i = 0; i < 2; i++) {                 /* Dont use the third axes (z). */
  490.         res[i] = trans_mat[3][i];     /* Initiate it with the weight factor. */
  491.         for (j = 0; j < 3; j++) res[i] += v[j] * trans_mat[j][i];
  492.     }
  493.  
  494.     for (i = 0; i < 3; i++) w += v[i] * trans_mat[i][3];
  495.     if (w == 0) w = 1e-5;
  496.  
  497.     *xt = ((int) (res[0] * xscaler / w)) + xmiddle;
  498.     *yt = ((int) (res[1] * yscaler / w)) + ymiddle;
  499. }
  500.  
  501. /* And the functions to map from user 3D space to terminal z coordinate */
  502. #ifdef THINK_C
  503. int map3d_z(x, y, z)
  504. #else
  505. static int map3d_z(x, y, z)
  506. #endif
  507. double x, y, z;
  508. {
  509.     int i, zt;
  510.     double v[4], res,                 /* Homogeneous coords. vectors. */
  511.     w = trans_mat[3][3];
  512.  
  513.     v[0] = map_x3d(x); /* Normalize object space to -1..1 */
  514.     v[1] = map_y3d(y);
  515.     v[2] = map_z3d(z);
  516.     v[3] = 1.0;
  517.  
  518.     res = trans_mat[3][2];               /* Initiate it with the weight factor. */
  519.     for (i = 0; i < 3; i++) res += v[i] * trans_mat[i][2];
  520.     if(w==0) w= 1e-5;
  521.     for (i = 0; i < 3; i++) w += v[i] * trans_mat[i][3];
  522.     zt = ((int) (res * 16384 / w));
  523.     return  zt;
  524. }
  525. #endif /* defined(THINK_C_4) */
  526.  
  527. #if defined(THINK_C_3)
  528.  
  529. /* Initialize the line style using the current device and set hidden styles  */
  530. /* to it as well if hidden line removal is enabled.                 */
  531. #ifdef THINK_C
  532. setlinestyle(style)
  533. #else
  534. static setlinestyle(style)
  535. #endif
  536. int style;
  537. {
  538.     register struct termentry *t = &term_tbl[term];
  539.  
  540.     (*t->linetype)(style);
  541.  
  542. #ifndef LITE
  543.     if (hidden3d) {
  544.     hidden_line_type_above = style;
  545.     hidden_line_type_below = style;
  546.     }
  547. #endif  /* LITE */
  548. }
  549.  
  550. #ifndef LITE
  551. /* Initialize the necessary steps for hidden line removal. */
  552. static void init_hidden_line_removal()
  553. {
  554.   int i;
  555.   /*  We want to keep the bitmap size less than 2048x2048, so we choose
  556.    *  integer dividers for the x and y coordinates to keep the x and y
  557.    *  ranges less than 2048.  In practice, the x and y sizes for the bitmap
  558.    *  will be somewhere between 1024 and 2048, except in cases where the
  559.    *  coordinates ranges for the device are already less than 1024.
  560.    *  We do this mainly to control the size of the bitmap, but it also
  561.    *  speeds up the computation.  We maintain separate dividers for
  562.    *  x and y.
  563.    */
  564.   xfact = (xright-xleft)/1024;
  565.   yfact = (ytop-ybot)/1024;
  566.   if(xfact == 0) xfact=1;
  567.   if(yfact == 0) yfact=1;
  568.   if(pnt == 0){
  569.     i = sizeof(short int*)*(XREDUCE(xright) - XREDUCE(xleft) + 1);
  570.     pnt = (short int **) alloc((unsigned long)i, "hidden");
  571.     bzero(pnt,i);
  572.   };
  573.   ymin_hl = (short int *) alloc((unsigned long)sizeof(short int)*
  574.                 (XREDUCE(xright) - XREDUCE(xleft) + 1), "hidden");
  575.   ymax_hl = (short int *) alloc((unsigned long)sizeof(short int)*
  576.                 (XREDUCE(xright) - XREDUCE(xleft) + 1), "hidden");
  577. }
  578.  
  579. /* Reset the hidden line data to a fresh start.                     */
  580. static void reset_hidden_line_removal()
  581. {
  582.     int i;
  583.     if(pnt){
  584.       for(i=0;i<=XREDUCE(xright)-XREDUCE(xleft);i++) {
  585.     if(pnt[i])
  586.       { free(pnt[i]); pnt[i] = 0;};
  587.       };
  588.     };
  589. }
  590.  
  591. /* Terminates the hidden line removal process. Free any memory allocated by  */
  592. /* init_hidden_line_removal above.                         */
  593. static void term_hidden_line_removal()
  594. {
  595.      if(pnt){
  596.        int j;
  597.        for(j=0;j<=XREDUCE(xright)-XREDUCE(xleft);j++) {
  598.      if(pnt[j])
  599.        { free(pnt[j]); pnt[j] = 0;};
  600.        };
  601.        free(pnt);
  602.        pnt = 0;
  603.      };
  604.    free(ymin_hl);
  605.    free(ymax_hl);
  606. }
  607. #endif /* not LITE */
  608.  
  609. /* Test a single point to be within the xleft,xright,ybot,ytop bbox.
  610.  * Sets the returned integers 4 l.s.b. as follows:
  611.  * bit 0 if to the left of xleft.
  612.  * bit 1 if to the right of xright.
  613.  * bit 2 if above of ytop.
  614.  * bit 3 if below of ybot.
  615.  * 0 is returned if inside.
  616.  */
  617. static int clip_point(x, y)
  618. int x, y;
  619. {
  620.     int ret_val = 0;
  621.  
  622.     if (x < xleft) ret_val |= 0x01;
  623.     if (x > xright) ret_val |= 0x02;
  624.     if (y < ybot) ret_val |= 0x04;
  625.     if (y > ytop) ret_val |= 0x08;
  626.  
  627.     return ret_val;
  628. }
  629.  
  630.  
  631. /* Clip the given line to drawing coords defined as xleft,xright,ybot,ytop.
  632.  *   This routine uses the cohen & sutherland bit mapping for fast clipping -
  633.  * see "Principles of Interactive Computer Graphics" Newman & Sproull page 65.
  634.  */
  635. static void draw_clip_line(x1, y1, x2, y2)
  636. int x1, y1, x2, y2;
  637. {
  638.     int x, y, dx, dy, x_intr[2], y_intr[2], count, pos1, pos2;
  639.     register struct termentry *t = &term_tbl[term];
  640.  
  641.     pos1 = clip_point(x1, y1);
  642.     pos2 = clip_point(x2, y2);
  643.     if (pos1 || pos2) {
  644.     if (pos1 & pos2) return;          /* segment is totally out. */
  645.  
  646.     /* Here part of the segment MAY be inside. test the intersection
  647.      * of this segment with the 4 boundaries for hopefully 2 intersections
  648.      * in. If non found segment is totaly out.
  649.      */
  650.     count = 0;
  651.     dx = x2 - x1;
  652.     dy = y2 - y1;
  653.  
  654.     /* Find intersections with the x parallel bbox lines: */
  655.     if (dy != 0) {
  656.         x = (ybot - y2) * dx / dy + x2;        /* Test for ybot boundary. */
  657.         if (x >= xleft && x <= xright) {
  658.         x_intr[count] = x;
  659.         y_intr[count++] = ybot;
  660.         }
  661.         x = (ytop - y2) * dx / dy + x2;        /* Test for ytop boundary. */
  662.         if (x >= xleft && x <= xright) {
  663.         x_intr[count] = x;
  664.         y_intr[count++] = ytop;
  665.         }
  666.     }
  667.  
  668.     /* Find intersections with the y parallel bbox lines: */
  669.     if (dx != 0) {
  670.         y = (xleft - x2) * dy / dx + y2;      /* Test for xleft boundary. */
  671.         if (y >= ybot && y <= ytop) {
  672.         x_intr[count] = xleft;
  673.         y_intr[count++] = y;
  674.         }
  675.         y = (xright - x2) * dy / dx + y2;    /* Test for xright boundary. */
  676.         if (y >= ybot && y <= ytop) {
  677.         x_intr[count] = xright;
  678.         y_intr[count++] = y;
  679.         }
  680.     }
  681.  
  682.     if (count == 2) {
  683.         int x_max, x_min, y_max, y_min;
  684.  
  685.         x_min = min(x1, x2);
  686.         x_max = max(x1, x2);
  687.         y_min = min(y1, y2);
  688.         y_max = max(y1, y2);
  689.  
  690.         if (pos1 && pos2) {               /* Both were out - update both */
  691.         x1 = x_intr[0];
  692.         y1 = y_intr[0];
  693.         x2 = x_intr[1];
  694.         y2 = y_intr[1];
  695.         }
  696.         else if (pos1) {           /* Only x1/y1 was out - update only it */
  697.         if (dx * (x2 - x_intr[0]) + dy * (y2 - y_intr[0]) > 0) {
  698.             x1 = x_intr[0];
  699.             y1 = y_intr[0];
  700.         }
  701.         else {
  702.             x1 = x_intr[1];
  703.             y1 = y_intr[1];
  704.         }
  705.         }
  706.         else {                      /* Only x2/y2 was out - update only it */
  707.         if (dx * (x_intr[0] - x1) + dy * (y_intr[0] - x1) > 0) {
  708.             x2 = x_intr[0];
  709.             y2 = y_intr[0];
  710.         }
  711.         else {
  712.             x2 = x_intr[1];
  713.             y2 = y_intr[1];
  714.         }
  715.         }
  716.  
  717.         if (x1 < x_min || x1 > x_max ||
  718.         x2 < x_min || x2 > x_max ||
  719.         y1 < y_min || y1 > y_max ||
  720.         y2 < y_min || y2 > y_max) return;
  721.     }
  722.     else
  723.         return;
  724.     }
  725.  
  726. #ifndef LITE
  727.     if(hidden3d && draw_surface)
  728.       {
  729.     char flag;
  730.     register int xv, yv, errx, erry, err;
  731.     register int xvr, yvr;
  732.     int xve, yve;
  733.     register int dy, nstep, dyr;
  734.     int i;
  735.     if (x1 > x2){
  736.       xvr = x2;
  737.       yvr = y2;
  738.       xve = x1;
  739.       yve = y1;
  740.     } else {
  741.       xvr = x1;
  742.       yvr = y1;
  743.       xve = x2;
  744.       yve = y2;
  745.     };
  746.     errx = XREDUCE(xve) - XREDUCE(xvr);
  747.     erry = YREDUCE(yve) - YREDUCE(yvr);
  748.     dy = (erry > 0 ? 1 : -1);
  749.     dyr = dy*yfact;
  750.     switch (dy){
  751.     case 1:
  752.       nstep = errx + erry;
  753.       errx = -errx;
  754.       break;
  755.     case -1:
  756.       nstep = errx - erry;
  757.       errx = -errx;
  758.       erry = -erry;
  759.       break;
  760.     };
  761.     err = errx + erry;
  762.     errx <<= 1;
  763.     erry <<= 1;
  764.     xv = XREDUCE(xvr) - XREDUCE(xleft);
  765.     yv = YREDUCE(yvr) - YREDUCE(ybot);
  766.     (*t->move)(xvr,yvr);
  767.     if( !IFSET(xv,yv) ) flag = 0;
  768.     else flag = 1;
  769.     if(!hidden_no_update){ /* Check first point */
  770.       if (xv < xmin_hl) xmin_hl = xv;
  771.       if (xv > xmax_hl) xmax_hl = xv;
  772.       if (yv > ymax_hl[xv]) ymax_hl[xv] = yv;
  773.       if (yv < ymin_hl[xv]) ymin_hl[xv] = yv;
  774.     };
  775.     for (i=0;i<nstep;i++){
  776.       if (err < 0){
  777.         xv ++;
  778.         xvr += xfact;
  779.         err += erry;
  780.       } else {
  781.         yv += dy;
  782.         yvr += dyr;
  783.         err += errx;
  784.       };
  785.       if( !IFSET(xv,yv)){
  786.         if(flag != 0) {(*t->move)(xvr,yvr); flag = 0;};
  787.       } else {
  788.         if(flag == 0) {(*t->vector)(xvr,yvr); flag = 1;};
  789.       };
  790.       if(!hidden_no_update){
  791.         if (xv < xmin_hl) xmin_hl = xv;
  792.         if (xv > xmax_hl) xmax_hl = xv;
  793.         if (yv > ymax_hl[xv]) ymax_hl[xv] = yv;
  794.         if (yv < ymin_hl[xv]) ymin_hl[xv] = yv;
  795.       };
  796.     };
  797.     if (flag == 0) (*t->vector)(xve, yve);
  798.     return;
  799.       };
  800. #endif /* not LITE */
  801.     if(!suppressMove) (*t->move)(x1,y1);
  802.     (*t->vector)(x2,y2);
  803. }
  804.  
  805. #endif /* defined(THINK_C_3) */
  806.  
  807.  
  808. /* Two routine to emulate move/vector sequence using line drawing routine. */
  809. #if defined(THINK_C_3)
  810. int move_pos_x, move_pos_y;
  811. #elif defined(THINK_C_4)
  812. extern int move_pos_x, move_pos_y;
  813. #else
  814. static int move_pos_x, move_pos_y;
  815. #endif
  816.  
  817. #if defined(THINK_C_3)
  818.  
  819. #ifdef THINK_C
  820. void clip_move(x,y)
  821. #else
  822. static void clip_move(x,y)
  823. #endif
  824. int x,y;
  825. {
  826.     move_pos_x = x;
  827.     move_pos_y = y;
  828. }
  829.  
  830. #ifdef THINK_C
  831. void clip_vector(x,y)
  832. #else
  833. static void clip_vector(x,y)
  834. #endif
  835. int x,y;
  836. {
  837.     draw_clip_line(move_pos_x,move_pos_y, x, y);
  838.     move_pos_x = x;
  839.     move_pos_y = y;
  840. }
  841.  
  842. /* And text clipping routine. */
  843. #ifdef THINK_C
  844. void clip_put_text(x, y, str)
  845. #else
  846. static void clip_put_text(x, y, str)
  847. #endif
  848. int x,y;
  849. char *str;
  850. {
  851.     register struct termentry *t = &term_tbl[term];
  852.  
  853.     if (clip_point(x, y)) return;
  854.  
  855.     (*t->put_text)(x,y,str);
  856. }
  857.  
  858. #endif /* (defined(THINK_C_3) */
  859.  
  860.  
  861. /* (DFK) For some reason, the Sun386i compiler screws up with the CheckLog 
  862.  * macro, so I write it as a function on that machine.
  863.  */
  864. #ifndef sun386
  865. /* (DFK) Use 10^x if logscale is in effect, else x */
  866. #define CheckLog(is_log, base_log, x) ((is_log) ? pow(base_log, (x)) : (x))
  867. #else
  868. static double CheckLog(is_log, base_log, x)
  869.      TBOOLEAN is_log;
  870.      double base_log;
  871.      double x;
  872. {
  873.   if (is_log)
  874.     return(pow(base_log, x));
  875.   else
  876.     return(x);
  877. }
  878. #endif /* sun386 */
  879.  
  880. #if defined(THINK_C_3)
  881.  
  882. static double
  883. LogScale(coord, is_log, log_base_log, what, axis)
  884.     double coord;            /* the value */
  885.     TBOOLEAN is_log;            /* is this axis in logscale? */
  886.     double log_base_log;        /* if so, the log of its base */
  887.     char *what;            /* what is the coord for? */
  888.     char *axis;            /* which axis is this for ("x" or "y")? */
  889. {
  890.     if (is_log) {
  891.        if (coord <= 0.0) {
  892.           char errbuf[100];        /* place to write error message */
  893.         (void) sprintf(errbuf,"%s has %s coord of %g; must be above 0 for log scale!",
  894.                 what, axis, coord);
  895.           (*term_tbl[term].text)();
  896.           (void) fflush(outfile);
  897.           int_error(errbuf, NO_CARET);
  898.        } else
  899.         return(log(coord)/log_base_log);
  900.     }
  901.     return(coord);
  902. }
  903.  
  904. /* borders of plotting area */
  905. /* computed once on every call to do_plot */
  906. static boundary3d(scaling)
  907.     TBOOLEAN scaling;        /* TRUE if terminal is doing the scaling */
  908. {
  909.     register struct termentry *t = &term_tbl[term];
  910.     /* luecken@udel.edu modifications
  911.        sizes the plot to take up more of available resolution */
  912.     xleft = (t->h_char)*2 + (t->h_tic);
  913.     xright = (scaling ? 1 : xsize) * (t->xmax) - (t->h_char)*2 - (t->h_tic);
  914.     ybot = (t->v_char)*5/2 + 1;
  915.     ytop = (scaling ? 1 : ysize) * (t->ymax) - (t->v_char)*5/2 - 1;
  916.     xmiddle = (xright + xleft) / 2;
  917.     ymiddle = (ytop + ybot) / 2;
  918.     xscaler = (xright - xleft) * 4 / 7;
  919.     yscaler = (ytop - ybot) * 4 / 7;
  920. }
  921.  
  922. static double dbl_raise(x,y)
  923. double x;
  924. int y;
  925. {
  926. register int i;
  927. double val;
  928.  
  929.     val = 1.0;
  930.     for (i=0; i < abs(y); i++)
  931.         val *= x;
  932.     if (y < 0 ) return (1.0/val);
  933.     return(val);
  934. }
  935.  
  936. #ifdef THINK_C
  937. double make_3dtics(tmin,tmax,axis,logscale, base_log)
  938. #else
  939. static double make_3dtics(tmin,tmax,axis,logscale, base_log)
  940. #endif
  941. double tmin,tmax;
  942. int axis;
  943. TBOOLEAN logscale;
  944. double base_log;
  945. {
  946. int x1,y1,x2,y2;
  947. register double xr,xnorm,tics,tic,l10;
  948.  
  949.     xr = fabs(tmin-tmax);
  950.  
  951.     /* Compute length of axis in screen space coords. */
  952.     switch (axis) {
  953.         case 'x':
  954.             map3d_xy(tmin,0.0,0.0,&x1,&y1);
  955.             map3d_xy(tmax,0.0,0.0,&x2,&y2);
  956.             break;
  957.         case 'y':
  958.             map3d_xy(0.0,tmin,0.0,&x1,&y1);
  959.             map3d_xy(0.0,tmax,0.0,&x2,&y2);
  960.             break;
  961.         case 'z':
  962.             map3d_xy(0.0,0.0,tmin,&x1,&y1);
  963.             map3d_xy(0.0,0.0,tmax,&x2,&y2);
  964.             break;
  965.     }
  966.  
  967.     if (((long) (x1-x2))*(x1-x2) + ((long) (y1-y2))*(y1-y2) <
  968.         sqr(3L * term_tbl[term].h_char))
  969.         return -1.0;                              /* No tics! */
  970.  
  971.     l10 = log10(xr);
  972.     if (logscale) {
  973.         tic = dbl_raise(base_log,(l10 >= 0.0 ) ? (int)l10 : ((int)l10-1));
  974.         if (tic < 1.0)
  975.             tic = 1.0;
  976.     } else {
  977.         xnorm = pow(10.0,l10-(double)((l10 >= 0.0 ) ? (int)l10 : ((int)l10-1)));
  978.         if (xnorm <= 5)
  979.             tics = 0.5;
  980.         else tics = 1.0;
  981.         tic = tics * dbl_raise(10.0,(l10 >= 0.0 ) ? (int)l10 : ((int)l10-1));
  982.     }
  983.     return(tic);
  984. }
  985.  
  986. do_3dplot(plots, pcount, min_x, max_x, min_y, max_y, min_z, max_z)
  987. struct surface_points *plots;
  988. int pcount;            /* count of plots in linked list */
  989. double min_x, max_x;
  990. double min_y, max_y;
  991. double min_z, max_z;
  992. {
  993. register struct termentry *t = &term_tbl[term];
  994. register int surface;
  995. register struct surface_points *this_plot;
  996. int xl, yl, linetypeOffset = 0;
  997.             /* only a Pyramid would have this many registers! */
  998. double xtemp, ytemp, ztemp, temp;
  999. struct text_label *this_label;
  1000. struct arrow_def *this_arrow;
  1001. TBOOLEAN scaling;
  1002. transform_matrix mat;
  1003.  
  1004. /* Initiate transformation matrix using the global view variables. */
  1005.     mat_rot_z(surface_rot_z, trans_mat);
  1006.     mat_rot_x(surface_rot_x, mat);
  1007.     mat_mult(trans_mat, trans_mat, mat);
  1008.     mat_scale(surface_scale / 2.0, surface_scale / 2.0, surface_scale / 2.0, mat);
  1009.     mat_mult(trans_mat, trans_mat, mat);
  1010.  
  1011. /* modify min_z/max_z so it will zscale properly. */
  1012.     ztemp = (max_z - min_z) / (2.0 * surface_zscale);
  1013.     temp = (max_z + min_z) / 2.0;
  1014.     min_z = temp - ztemp;
  1015.     max_z = temp + ztemp;
  1016.  
  1017. /* store these in variables global to this file */
  1018. /* otherwise, we have to pass them around a lot */
  1019.     x_min3d = min_x;
  1020.     x_max3d = max_x;
  1021.     y_min3d = min_y;
  1022.     y_max3d = max_y;
  1023.     z_min3d = min_z;
  1024.     z_max3d = max_z;
  1025.  
  1026.     /* The extrema need to be set even when a surface is not being
  1027.      * drawn.   Without this, gnuplot used to assume that the X and
  1028.      * Y axis started at zero.   -RKC
  1029.      */
  1030.  
  1031.     /* find (bottom) left corner of grid */
  1032.     min_sx_ox = min_x;
  1033.     min_sx_oy = min_y;
  1034.     /* find bottom (right) corner of grid */
  1035.     min_sy_ox = max_x;
  1036.     min_sy_oy = min_y;
  1037.  
  1038.  
  1039.     if (polar)
  1040.     int_error("Cannot splot in polar coordinate system.", NO_CARET);
  1041.  
  1042.     if (z_min3d == VERYLARGE || z_max3d == -VERYLARGE ||
  1043.     x_min3d == VERYLARGE || x_max3d == -VERYLARGE ||
  1044.     y_min3d == VERYLARGE || y_max3d == -VERYLARGE)
  1045.         int_error("all points undefined!", NO_CARET);
  1046.  
  1047.     /* If we are to draw the bottom grid make sure zmin is updated properly. */
  1048.     if (xtics || ytics || grid)
  1049.     z_min3d -= (max_z - min_z) * ticslevel;
  1050.  
  1051. /*  This used be x_max3d == x_min3d, but that caused an infinite loop once. */
  1052.     if (fabs(x_max3d - x_min3d) < zero)
  1053.     int_error("x_min3d should not equal x_max3d!",NO_CARET);
  1054.     if (fabs(y_max3d - y_min3d) < zero)
  1055.     int_error("y_min3d should not equal y_max3d!",NO_CARET);
  1056.     if (fabs(z_max3d - z_min3d) < zero)
  1057.     int_error("z_min3d should not equal z_max3d!",NO_CARET);
  1058.  
  1059. #ifndef LITE
  1060.     if (hidden3d) {
  1061.     struct surface_points *plot;
  1062.   
  1063.         /* Verify data is hidden line removable - grid based. */
  1064.           for (plot = plots; plot != NULL; plot = plot->next_sp) {
  1065.          if (plot->plot_type == DATA3D && !plot->has_grid_topology){
  1066.           fprintf(stderr,"Notice: Cannot remove hidden lines from non grid data\n");
  1067.               return(0);
  1068.             }
  1069.     
  1070.         }
  1071.     }
  1072. #endif /* not LITE */
  1073.  
  1074. /* INITIALIZE TERMINAL */
  1075.     if (!term_init) {
  1076.     (*t->init)();
  1077.     term_init = TRUE;
  1078.     }
  1079.     screen_ok = FALSE;
  1080.     scaling = (*t->scale)(xsize, ysize);
  1081.     (*t->graphics)();
  1082.  
  1083.     /* now compute boundary for plot (xleft, xright, ytop, ybot) */
  1084.     boundary3d(scaling);
  1085.  
  1086. /* SCALE FACTORS */
  1087.     zscale3d = 2.0/(z_max3d - z_min3d);
  1088.     yscale3d = 2.0/(y_max3d - y_min3d);
  1089.     xscale3d = 2.0/(x_max3d - x_min3d);
  1090.  
  1091.     (*t->linetype)(-2); /* border linetype */
  1092.  
  1093. /* PLACE TITLE */
  1094.     if (*title != 0) {
  1095.         int x, y;
  1096.  
  1097.         x = title_xoffset * t->h_char;
  1098.         y = title_yoffset * t->v_char;
  1099.  
  1100.         if ((*t->justify_text)(CENTRE)) 
  1101.             (*t->put_text)(x+(xleft+xright)/2, 
  1102.                        y+ytop+(t->v_char), title);
  1103.         else
  1104.             (*t->put_text)(x+(xleft+xright)/2 - strlen(title)*(t->h_char)/2,
  1105.                        y+ytop+(t->v_char), title);
  1106.     }
  1107.  
  1108. /* PLACE TIMEDATE */
  1109.     if (timedate) {
  1110.         int x, y;
  1111.  
  1112.         x = time_xoffset * t->h_char;
  1113.         y = time_yoffset * t->v_char;
  1114.         dated = time( (time_t *) 0);
  1115.         tdate = ctime( &dated);
  1116.         tdate[24]='\0';
  1117.         if ((*t->text_angle)(1)) {
  1118.             if ((*t->justify_text)(CENTRE)) {
  1119.                 (*t->put_text)(x+(t->v_char),
  1120.                          y+ybot+4*(t->v_char), tdate);
  1121.             }
  1122.             else {
  1123.                 (*t->put_text)(x+(t->v_char),
  1124.                          y+ybot+4*(t->v_char)-(t->h_char)*strlen(ylabel)/2, 
  1125.                          tdate);
  1126.             }
  1127.         }
  1128.         else {
  1129.             (void)(*t->justify_text)(LEFT);
  1130.             (*t->put_text)(x,
  1131.                          y+ybot-1*(t->v_char), tdate);
  1132.         }
  1133.         (void)(*t->text_angle)(0);
  1134.     }
  1135.  
  1136. /* PLACE LABELS */
  1137.     for (this_label = first_label; this_label!=NULL;
  1138.             this_label=this_label->next ) {
  1139.         int x,y;
  1140.  
  1141.         xtemp = LogScale(this_label->x, is_log_x, log_base_log_x, "label", "x");
  1142.         ytemp = LogScale(this_label->y, is_log_y, log_base_log_y, "label", "y");
  1143.         ztemp = LogScale(this_label->z, is_log_z, log_base_log_z, "label", "z");
  1144.             map3d_xy(xtemp,ytemp,ztemp, &x, &y);
  1145.  
  1146.         if ((*t->justify_text)(this_label->pos)) {
  1147.             (*t->put_text)(x,y,this_label->text);
  1148.         }
  1149.         else {
  1150.             switch(this_label->pos) {
  1151.                 case  LEFT:
  1152.                     (*t->put_text)(x,y,this_label->text);
  1153.                     break;
  1154.                 case CENTRE:
  1155.                     (*t->put_text)(x -
  1156.                         (t->h_char)*strlen(this_label->text)/2,
  1157.                         y, this_label->text);
  1158.                     break;
  1159.                 case RIGHT:
  1160.                     (*t->put_text)(x -
  1161.                         (t->h_char)*strlen(this_label->text),
  1162.                         y, this_label->text);
  1163.                     break;
  1164.             }
  1165.          }
  1166.      }
  1167.  
  1168. /* PLACE ARROWS */
  1169.     (*t->linetype)(0);    /* arrow line type */
  1170.     for (this_arrow = first_arrow; this_arrow!=NULL;
  1171.         this_arrow = this_arrow->next ) {
  1172.     int sx,sy,ex,ey;
  1173.  
  1174.     xtemp = LogScale(this_arrow->sx, is_log_x, log_base_log_x, "arrow", "x");
  1175.     ytemp = LogScale(this_arrow->sy, is_log_y, log_base_log_y, "arrow", "y");
  1176.     ztemp = LogScale(this_arrow->sz, is_log_z, log_base_log_z, "arrow", "z");
  1177.     map3d_xy(xtemp,ytemp,ztemp, &sx, &sy);
  1178.  
  1179.     xtemp = LogScale(this_arrow->ex, is_log_x, log_base_log_x, "arrow", "x");
  1180.     ytemp = LogScale(this_arrow->ey, is_log_y, log_base_log_y, "arrow", "y");
  1181.     ztemp = LogScale(this_arrow->ez, is_log_z, log_base_log_z, "arrow", "z");
  1182.     map3d_xy(xtemp,ytemp,ztemp, &ex, &ey);
  1183.  
  1184.     (*t->arrow)(sx, sy, ex, ey, this_arrow->head);
  1185.     }
  1186.  
  1187. #ifndef LITE
  1188.     if (hidden3d && draw_surface) {
  1189.     init_hidden_line_removal();
  1190.     reset_hidden_line_removal();
  1191.     hidden_active = TRUE;
  1192.     }
  1193. #endif /* not LITE */
  1194.  
  1195. /* DRAW SURFACES AND CONTOURS */
  1196.     real_z_min3d = min_z;
  1197.     real_z_max3d = max_z;
  1198.     if (key == -1) {
  1199.         xl = xright  - (t->h_tic) - (t->h_char)*5;
  1200.         yl = ytop - (t->v_tic) - (t->v_char);
  1201.     }
  1202.     if (key == 1) {
  1203.         xtemp = LogScale(key_x, is_log_x, log_base_log_x, "key", "x");
  1204.         ytemp = LogScale(key_y, is_log_y, log_base_log_y, "key", "y");
  1205.         ztemp = LogScale(key_z, is_log_z, log_base_log_z, "key", "z");
  1206.         map3d_xy(xtemp,ytemp,ztemp, &xl, &yl);
  1207.     }
  1208.  
  1209. #ifndef LITE
  1210.     if (hidden3d && draw_surface) plot3d_hidden(plots,pcount);
  1211. #endif /* not LITE */
  1212.     this_plot = plots;
  1213.     for (surface = 0;
  1214.          surface < pcount;
  1215.          this_plot = this_plot->next_sp, surface++) {
  1216. #ifndef LITE
  1217.         if ( hidden3d )
  1218.             hidden_no_update = FALSE;
  1219. #endif /* not LITE */
  1220.  
  1221.         if (draw_surface) {
  1222.             (*t->linetype)(this_plot->line_type);
  1223. #ifndef LITE
  1224.             if (hidden3d) {
  1225.             hidden_line_type_above = this_plot->line_type;
  1226.             hidden_line_type_below = this_plot->line_type + 1;
  1227.             }
  1228. #endif /* not LITE */            
  1229.             if (key != 0 && this_plot->title) {
  1230.             if ((*t->justify_text)(RIGHT)) {
  1231.                 clip_put_text(xl,
  1232.                       yl,this_plot->title);
  1233.             }
  1234.             else {
  1235.                 if (inrange(xl-(t->h_char)*strlen(this_plot->title), 
  1236.                     xleft, xright))
  1237.                 clip_put_text(xl-(t->h_char)*strlen(this_plot->title),
  1238.                           yl,this_plot->title);
  1239.             }
  1240.             }
  1241.             
  1242.             switch(this_plot->plot_style) {
  1243.                 case BOXES: /* can't do boxes in 3d yet so use impulses */
  1244.                 case IMPULSES: {
  1245.                 if (key != 0 && this_plot->title) {
  1246.                 clip_move(xl+(t->h_char),yl);
  1247.                 clip_vector(xl+4*(t->h_char),yl);
  1248.                 }
  1249.                 if (!(hidden3d && draw_surface))
  1250.                   plot3d_impulses(this_plot);
  1251.                 break;
  1252.             }
  1253.             case LINES: {
  1254.                 if (key != 0 && this_plot->title) {
  1255.                 clip_move(xl+(int)(t->h_char),yl);
  1256.                 clip_vector(xl+(int)(4*(t->h_char)),yl);
  1257.                 }
  1258.                 if (!(hidden3d && draw_surface))
  1259.                   plot3d_lines(this_plot);
  1260.                 break;
  1261.             }
  1262.             case ERRORBARS:    /* ignored; treat like points */
  1263.             case POINTSTYLE: {
  1264.                 if (key != 0 && this_plot->title 
  1265.                 && !clip_point(xl+2*(t->h_char),yl)) {
  1266.                 (*t->point)(xl+2*(t->h_char),yl,
  1267.                         this_plot->point_type);
  1268.                 }
  1269.                 if (!(hidden3d && draw_surface))
  1270.                   plot3d_points(this_plot);
  1271.                 break;
  1272.             }
  1273.             case LINESPOINTS: {
  1274.                 /* put lines */
  1275.                 if (key != 0 && this_plot->title) {
  1276.                 clip_move(xl+(t->h_char),yl);
  1277.                 clip_vector(xl+4*(t->h_char),yl);
  1278.                 }
  1279.                  if (!(hidden3d && draw_surface))
  1280.                    plot3d_lines(this_plot);
  1281.             
  1282.                 /* put points */
  1283.                 if (key != 0 && this_plot->title 
  1284.                 && !clip_point(xl+2*(t->h_char),yl)) {
  1285.                 (*t->point)(xl+2*(t->h_char),yl,
  1286.                         this_plot->point_type);
  1287.                 }
  1288.                 if (!(hidden3d && draw_surface))
  1289.                   plot3d_points(this_plot);
  1290.                 break;
  1291.             }
  1292.             case DOTS: {
  1293.                 if (key != 0 && this_plot->title
  1294.                 && !clip_point(xl+2*(t->h_char),yl)) {
  1295.                 (*t->point)(xl+2*(t->h_char),yl, -1);
  1296.                 }
  1297.                 if (!(hidden3d && draw_surface))
  1298.                   plot3d_dots(this_plot);
  1299.                 break;
  1300.             }
  1301.             }
  1302.             if (key != 0 && this_plot->title)
  1303.                 yl = yl - (t->v_char);
  1304.         }
  1305.  
  1306. #ifndef LITE
  1307.         if ( hidden3d ) {
  1308.             hidden_no_update = TRUE;
  1309.             hidden_line_type_above = this_plot->line_type + (hidden3d ? 2 : 1);
  1310.             hidden_line_type_below = this_plot->line_type + (hidden3d ? 2 : 1);
  1311.         }
  1312. #endif /* not LITE */
  1313.  
  1314.         if (draw_contour && this_plot->contours != NULL) {
  1315.             struct gnuplot_contours *cntrs = this_plot->contours;
  1316.  
  1317.             (*t->linetype)(this_plot->line_type + (hidden3d ? 2 : 1));
  1318.  
  1319.             if (key != 0 && this_plot->title 
  1320.                       && !(draw_surface && label_contours) ) {
  1321.                 if ((*t->justify_text)(RIGHT)) {
  1322.                     clip_put_text(xl,
  1323.                         yl,this_plot->title);
  1324.                 }
  1325.                 else {
  1326.                     if (inrange(xl-(t->h_char)*strlen(this_plot->title), 
  1327.                              xleft, xright))
  1328.                      clip_put_text(xl-(t->h_char)*strlen(this_plot->title),
  1329.                                  yl,this_plot->title);
  1330.                 }
  1331.                 switch(this_plot->plot_style) {
  1332.                     case IMPULSES:
  1333.                         clip_move(xl+(t->h_char),yl);
  1334.                         clip_vector(xl+4*(t->h_char),yl);
  1335.                         break;
  1336.                     case LINES:
  1337.                         clip_move(xl+(int)(t->h_char),yl);
  1338.                         clip_vector(xl+(int)(4*(t->h_char)),yl);
  1339.                         break;
  1340.                     case ERRORBARS: /* ignored; treat like points */
  1341.                     case POINTSTYLE:
  1342.                         if (!clip_point(xl+2*(t->h_char),yl)) {
  1343.                              (*t->point)(xl+2*(t->h_char),yl,
  1344.                                     this_plot->point_type);
  1345.                         }
  1346.                         break;
  1347.                     case LINESPOINTS:
  1348.                         clip_move(xl+(int)(t->h_char),yl);
  1349.                         clip_vector(xl+(int)(4*(t->h_char)),yl);
  1350.                         break;
  1351.                     case DOTS:
  1352.                         if (!clip_point(xl+2*(t->h_char),yl)) {
  1353.                              (*t->point)(xl+2*(t->h_char),yl, -1);
  1354.                         }
  1355.                         break;
  1356.                 }
  1357.                 yl = yl - (t->v_char);
  1358.             }
  1359.             yl = yl + (t->v_char);
  1360.  
  1361.              linetypeOffset = this_plot->line_type + (hidden3d ? 2 : 1);
  1362.             while (cntrs) {
  1363.                  if(label_contours && cntrs->isNewLevel) {
  1364.                      (*t->linetype)(linetypeOffset++);
  1365. #ifndef LITE
  1366.                      if(hidden3d) hidden_line_type_below = hidden_line_type_above = linetypeOffset-1;
  1367. #endif /* not LITE */
  1368.                      yl -= (t->v_char);
  1369.                      if ((*t->justify_text)(RIGHT)) {
  1370.                         clip_put_text(xl,
  1371.                             yl,cntrs->label);
  1372.                     }
  1373.                     else {
  1374.                         if (inrange(xl-(t->h_char)*strlen(cntrs->label),
  1375.                                  xleft, xright))
  1376.                          clip_put_text(xl-(t->h_char)*strlen(cntrs->label),
  1377.                                      yl,cntrs->label);
  1378.                     }
  1379.                     switch(this_plot->plot_style) {
  1380.                         case IMPULSES:
  1381.                             clip_move(xl+(t->h_char),yl);
  1382.                             clip_vector(xl+4*(t->h_char),yl);
  1383.                             break;
  1384.                         case LINES:
  1385.                             clip_move(xl+(int)(t->h_char),yl);
  1386.                             clip_vector(xl+(int)(4*(t->h_char)),yl);
  1387.                             break;
  1388.                         case ERRORBARS: /* ignored; treat like points */
  1389.                         case POINTSTYLE:
  1390.                             if (!clip_point(xl+2*(t->h_char),yl)) {
  1391.                                  (*t->point)(xl+2*(t->h_char),yl,
  1392.                                         this_plot->point_type);
  1393.                             }
  1394.                             break;
  1395.                         case LINESPOINTS:
  1396.                             clip_move(xl+(int)(t->h_char),yl);
  1397.                             clip_vector(xl+(int)(4*(t->h_char)),yl);
  1398.                             break;
  1399.                         case DOTS:
  1400.                             if (!clip_point(xl+2*(t->h_char),yl)) {
  1401.                                  (*t->point)(xl+2*(t->h_char),yl, -1);
  1402.                             }
  1403.                             break;
  1404.                     }
  1405.                  }
  1406.                 switch(this_plot->plot_style) {
  1407.                     case IMPULSES:
  1408.                            cntr3d_impulses(cntrs, this_plot);
  1409.                         break;
  1410.                     case LINES:
  1411.                         cntr3d_lines(cntrs);
  1412.                         break;
  1413.                     case ERRORBARS: /* ignored; treat like points */
  1414.                     case POINTSTYLE:
  1415.                         cntr3d_points(cntrs, this_plot);
  1416.                         break;
  1417.                     case LINESPOINTS:
  1418.                         cntr3d_lines(cntrs);
  1419.                         cntr3d_points(cntrs, this_plot);
  1420.                         break;
  1421.                     case DOTS:
  1422.                         cntr3d_dots(cntrs);
  1423.                         break;
  1424.                 }
  1425.                 cntrs = cntrs->next;
  1426.             }
  1427.             if (key != 0 && this_plot->title)
  1428.               yl = yl - (t->v_char);
  1429.         }
  1430.  
  1431.         if (surface == 0)
  1432.             draw_bottom_grid(this_plot,real_z_min3d,real_z_max3d);
  1433.     }
  1434.     (*t->text)();
  1435.     (void) fflush(outfile);
  1436.  
  1437. #ifndef LITE
  1438.     if (hidden3d) {
  1439.         term_hidden_line_removal();
  1440.         hidden_active = FALSE;
  1441.     }
  1442. #endif /* not LITE */
  1443. }
  1444.  
  1445. /* plot3d_impulses:
  1446.  * Plot the surfaces in IMPULSES style
  1447.  */
  1448. static plot3d_impulses(plot)
  1449.     struct surface_points *plot;
  1450. {
  1451.     int i;                /* point index */
  1452.     int x,y,x0,y0;            /* point in terminal coordinates */
  1453.     struct iso_curve *icrvs = plot->iso_crvs;
  1454.  
  1455.     while ( icrvs ) {
  1456.     struct coordinate GPHUGE *points = icrvs->points;
  1457.  
  1458.     for (i = 0; i < icrvs->p_count; i++) {
  1459.         if (real_z_max3d<points[i].z)
  1460.         real_z_max3d=points[i].z;
  1461.         if (real_z_min3d>points[i].z)
  1462.         real_z_min3d=points[i].z;
  1463.  
  1464.         map3d_xy(points[i].x, points[i].y, points[i].z, &x, &y);
  1465.         map3d_xy(points[i].x, points[i].y, z_min3d, &x0, &y0);
  1466.  
  1467.         clip_move(x0,y0);
  1468.         clip_vector(x,y);
  1469.     }
  1470.  
  1471.     icrvs = icrvs->next;
  1472.     }
  1473. }
  1474.  
  1475. /* plot3d_lines:
  1476.  * Plot the surfaces in LINES style
  1477.  */
  1478. /* We want to always draw the lines in the same direction, otherwise when
  1479.    we draw an adjacent box we might get the line drawn a little differently
  1480.    and we get splotches.  */
  1481.  
  1482. #ifndef LITE
  1483.  
  1484. static int zsort( r1, r2)
  1485. int * r1;
  1486. int * r2;
  1487. {
  1488.   int z1, z2;
  1489.   z1 = nodes[*r1].z;
  1490.   z2 = nodes[*r2].z;
  1491.   if (z1 < z2) return 1;
  1492.   if (z1 == z2) return 0;
  1493.   return -1;
  1494. }
  1495. #define TESTBOX(X,Y)                    \
  1496.   if(X<xmin_box) xmin_box = X;                \
  1497.   if(X>xmax_box) xmax_box = X;                \
  1498.   if(Y<ymin_box) ymin_box = Y;                \
  1499.   if(Y>ymax_box) ymax_box = Y;
  1500. /* Usefull macro to help us figure out which side of the surface we are on */
  1501. #define XPRD(I,J,K)                     \
  1502.   ((nodes[I].x-nodes[J].x)*(nodes[J].y-nodes[K].y) -    \
  1503.   (nodes[I].y-nodes[J].y)*(nodes[J].x-nodes[K].x))
  1504. #define MAYBE_LINEPOINT(J)                        \
  1505.     if((nodes[J].flag & 0x20) != 0) {                \
  1506.       x = nodes[J].x;                        \
  1507.       y = nodes[J].y;                        \
  1508.       nodes[J].flag -= 0x20;                    \
  1509.       if (!clip_point(x,y) &&                     \
  1510.       !IFSET(XREDUCE(x)-XREDUCE(xleft),YREDUCE(y)-YREDUCE(ybot))) \
  1511.     (*t->point)(x,y, plot_info[nplot].point_type);        \
  1512.     };
  1513.  
  1514. struct surface_plots{
  1515.   int above_color;
  1516.   int below_color;
  1517.   int row_offset;
  1518.   int point_type;
  1519. };
  1520. /* All of the plots coming into this routine are assumed to have grid
  1521.    topology.  */
  1522.  
  1523. static plot3d_hidden(plots, pcount)
  1524.      struct surface_points *plots;
  1525.      int pcount;
  1526. {
  1527.   struct surface_points *this_plot;
  1528.   long int i, j;
  1529.   int nplot;
  1530.   long int x,y,z ,nseg, ncrv, ncrv1;        /* point in terminal coordinates */
  1531. #ifdef AMIGA_SC_6_1
  1532.   unsigned short int * cpnt;
  1533. #else /* !AMIGA_SC_6_1 */
  1534.   short int * cpnt;
  1535. #endif /* !AMIGA_SC_6_1 */
  1536.   short int  mask1, mask2;
  1537.   long int indx1, indx2, k, m;
  1538.   short int xmin_box, xmax_box, ymin_box, ymax_box;
  1539.   struct surface_plots * plot_info;
  1540.   int row_offset, nnode;
  1541.   short int y_malloc;  /* Amount of space we need for one vertical row of
  1542.                           bitmap, and byte offset of first used element */
  1543.   struct termentry *t = &term_tbl[term];
  1544.   struct iso_curve *icrvs;
  1545.   int current_style = 0x7fff;  /* Current line style */
  1546.   int surface;
  1547.   nnode = 0;
  1548.   nseg = 0;
  1549.   nplot = 0;
  1550.   this_plot = plots;
  1551.  
  1552.   for (surface = 0;
  1553.        surface < pcount;
  1554.        this_plot = this_plot->next_sp, surface++) {
  1555.     nplot++;
  1556.     icrvs = plots->iso_crvs;
  1557.     icrvs = plots->iso_crvs;
  1558.     if(this_plot->plot_type == FUNC3D) {
  1559.         for(icrvs = this_plot->iso_crvs,ncrv=0;icrvs;icrvs=icrvs->next,ncrv++) { };
  1560.  /*      if(this_plot->has_grid_topology) ncrv >>= 1; */
  1561.     };
  1562.     if(this_plot->plot_type == DATA3D)
  1563.        ncrv = this_plot->num_iso_read;
  1564.     nnode += ncrv * (this_plot->iso_crvs->p_count);
  1565. /*    for(icrvs = this_plot->iso_crvs,ncrv=0;icrvs;icrvs=icrvs->next,ncrv++) { };
  1566.     nnode += ncrv * (this_plot->iso_crvs->p_count); */
  1567.     switch(this_plot->plot_style) {
  1568.     case ERRORBARS:
  1569.     case DOTS:
  1570.     case POINTSTYLE:
  1571.     case LINESPOINTS:
  1572.       nseg += (ncrv) * (this_plot->iso_crvs->p_count);
  1573.       break;
  1574.     case LINES:
  1575.       nseg += (ncrv-1) * (this_plot->iso_crvs->p_count-1);
  1576.       break;
  1577.     case IMPULSES:
  1578.       /* There will be two nodes for each segment */
  1579.       nnode += ncrv * (this_plot->iso_crvs->p_count);
  1580.       nseg += (ncrv) * (this_plot->iso_crvs->p_count);
  1581.       break;
  1582.     }
  1583.   };
  1584.   boxlist = (int *) alloc((unsigned long)sizeof(int)*nseg, "hidden");
  1585.   nodes = (struct pnts *) alloc((unsigned long)sizeof(struct pnts)*nnode, "hidden");
  1586.   plot_info = (struct surface_plots *) alloc((unsigned long)sizeof(struct surface_plots)*nplot,"hidden");
  1587.   nnode = 0;
  1588.   nseg = 0;
  1589.   nplot = 0;
  1590.   this_plot = plots;
  1591.   hidden_no_update = FALSE;
  1592.  
  1593.   if ( hidden3d && draw_surface)
  1594.     for (surface = 0;
  1595.      surface < pcount;
  1596.      this_plot = this_plot->next_sp, surface++) {
  1597.       (*t->linetype)(this_plot->line_type);
  1598.       hidden_line_type_above = this_plot->line_type;
  1599.         hidden_line_type_below = this_plot->line_type + 1;
  1600.     if(this_plot->plot_type == FUNC3D) {
  1601.       for(icrvs = this_plot->iso_crvs,ncrv=0;icrvs;icrvs=icrvs->next,ncrv++) { };
  1602. /*      if(this_plot->has_grid_topology) ncrv >>= 1; */
  1603.     };
  1604.     if(this_plot->plot_type == DATA3D)
  1605.       ncrv = this_plot->num_iso_read;
  1606.       icrvs = this_plot->iso_crvs;
  1607.       ncrv1 = ncrv;
  1608.       ncrv = 0;
  1609.       while ( icrvs) {
  1610.     struct coordinate GPHUGE *points = icrvs->points;
  1611.     for (i = 0; i < icrvs->p_count; i++) {
  1612.       map3d_xy(points[i].x, points[i].y, points[i].z,&nodes[nnode].x,&nodes[nnode].y);
  1613.       nodes[nnode].z = map3d_z(points[i].x, points[i].y, points[i].z);
  1614.       nodes[nnode].flag = (i==0 ? 1 : 0) + (ncrv == 0 ? 2 : 0) +
  1615.         (i == icrvs->p_count-1 ? 4 : 0) + (ncrv == ncrv1-1 ? 8 : 0);
  1616.       nodes[nnode].nplot = nplot;
  1617.       nodes[nnode].style_used = -1000; /* indicates no style */
  1618.       switch(this_plot->plot_style) {
  1619.       case LINESPOINTS:
  1620.         if(i < icrvs->p_count-1 && ncrv < ncrv1-1)
  1621.           nodes[nnode].flag |= 0x30;
  1622.         else
  1623.           nodes[nnode].flag |= 0x20;
  1624.         boxlist[nseg++] = nnode++;
  1625.         break;
  1626.       case LINES:
  1627.         if(i < icrvs->p_count-1 && ncrv < ncrv1-1)
  1628.           {
  1629.         nodes[nnode].flag |= 0x10;
  1630.         boxlist[nseg++] = nnode++;
  1631.           }
  1632.         else
  1633.           nnode++;
  1634.         break;
  1635.       case ERRORBARS:
  1636.       case POINTSTYLE:
  1637.       case DOTS:
  1638.         nodes[nnode].flag |= 0x40;
  1639.         boxlist[nseg++] = nnode++;
  1640.         break;
  1641.       case IMPULSES:
  1642.         nodes[nnode].flag |= 0x80;
  1643.         boxlist[nseg++] = nnode++;
  1644.         map3d_xy(points[i].x, points[i].y, z_min3d, &nodes[nnode].x,&nodes[nnode].y);
  1645.         nodes[nnode].z = map3d_z(points[i].x, points[i].y, z_min3d);
  1646.         nnode++;
  1647.         break;
  1648.         break;
  1649.       }
  1650.     }
  1651.     icrvs = icrvs->next;
  1652.     ncrv++;
  1653.     if(ncrv == ncrv1) break;
  1654.       }
  1655.       /* Next we go through all of the boxes, and substitute the average z value
  1656.      for the box for the z value of the corner node */
  1657.       plot_info[nplot].above_color = this_plot->line_type;
  1658.       plot_info[nplot].below_color = this_plot->line_type+1;
  1659.       plot_info[nplot].point_type =
  1660.     ((this_plot->plot_style == DOTS) ? -1 : this_plot->point_type);
  1661.       plot_info[nplot++].row_offset = this_plot->iso_crvs->p_count;
  1662.     }
  1663.       for(i=0; i<nseg; i++){
  1664.     j = boxlist[i];
  1665.     if ((nodes[j].flag & 0x80) != 0) {
  1666.       nodes[j].z = (nodes[j].z < nodes[j+1].z ? nodes[j].z : nodes[j+1].z);
  1667.       continue;
  1668.     };
  1669.     if ((nodes[j].flag & 0x10) == 0) continue;
  1670.     row_offset = plot_info[nodes[j].nplot].row_offset;
  1671.     z = nodes[j].z;
  1672.     if (z < nodes[j+1].z) z = nodes[j+1].z;
  1673.     if (z < nodes[j+row_offset].z) z = nodes[j+row_offset].z;
  1674.     if (z < nodes[j+row_offset+1].z) z = nodes[j+row_offset+1].z;
  1675.       };
  1676.   qsort (boxlist, nseg, sizeof(int), zsort);
  1677.   y_malloc = (2+ (YREDUCE(ytop)>>4) - (YREDUCE(ybot)>>4))*sizeof(short int);
  1678.   for(i=0;i<=(XREDUCE(xright)-XREDUCE(xleft));i++) {
  1679.     ymin_hl[i] = 0x7fff; 
  1680.     ymax_hl[i] = 0;
  1681.   };
  1682.   for(i=0;i<nseg;i++) {
  1683.     j = boxlist[i];
  1684.     nplot = nodes[j].nplot;
  1685.     row_offset = plot_info[nplot].row_offset;
  1686.     if((nodes[j].flag & 0x40) != 0) {
  1687.       x = nodes[j].x;
  1688.       y = nodes[j].y;
  1689.       if (!clip_point(x,y) &&
  1690.       !IFSET(XREDUCE(x)-XREDUCE(xleft),YREDUCE(y)-YREDUCE(ybot)))
  1691.     (*t->point)(x,y, plot_info[nplot].point_type);
  1692.     };
  1693.     if((nodes[j].flag & 0x80) != 0) { /* impulses */
  1694.       clip_move(nodes[j].x,nodes[j].y);
  1695.       clip_vector(nodes[j+1].x,nodes[j+1].y);
  1696.     };
  1697.     if((nodes[j].flag & 0x10) != 0) {
  1698. /* It is possible, and often profitable, to take a quick look and see
  1699.    if the current box is entirely obscured.  If this is the case we will
  1700.    not even bother testing this box any further.  */
  1701.       xmin_box = 0x7fff; 
  1702.       xmax_box = 0;
  1703.       ymin_box = 0x7fff; 
  1704.       ymax_box = 0;
  1705.       TESTBOX(nodes[j].x-xleft,nodes[j].y-ybot);
  1706.       TESTBOX(nodes[j+1].x-xleft,nodes[j+1].y-ybot);
  1707.       TESTBOX(nodes[j+row_offset].x-xleft,nodes[j+row_offset].y-ybot);
  1708.       TESTBOX(nodes[j+row_offset+1].x-xleft,nodes[j+row_offset+1].y-ybot);
  1709.       z=0;
  1710.       if(xmin_box < 0) xmin_box = 0;
  1711.       if(ymin_box < 0) ymin_box = 0;
  1712.       if(xmax_box > xright-xleft) xmax_box = xright-xleft;
  1713.       if(ymax_box > ytop-ybot) ymax_box = ytop-ybot;
  1714.       /* Now check bitmap.  These coordinates have not been reduced */
  1715.       if(xmin_box <= xmax_box && ymin_box <= ymax_box){
  1716.     ymin_box = YREDUCE(ymin_box);
  1717.     ymax_box = YREDUCE(ymax_box);
  1718.     xmin_box = XREDUCE(xmin_box);
  1719.     xmax_box = XREDUCE(xmax_box);
  1720.     indx1 = ymin_box >> 4;
  1721.     indx2 = ymax_box >> 4;
  1722.     mask1 = 0xffff << (ymin_box & 0x0f);
  1723.     mask2 = 0xffff >> (0x0f-(ymax_box & 0x0f));
  1724.     for(m=xmin_box;m<=xmax_box;m++) {
  1725.       if(pnt[m] == 0) {z++; break;};
  1726.       cpnt = pnt[m] + indx1;
  1727.       if(indx1 == indx2){
  1728.         if((*cpnt & mask1 & mask2) != (mask1 & mask2)) {z++; break;}
  1729.       } else {
  1730.         if((*cpnt++ & mask1) != mask1) {z++; break;}
  1731.         k = indx1+1;
  1732.         while (k != indx2) {
  1733.           if((unsigned short)*cpnt++ != 0xffff) {z++; break;}
  1734.           k++;
  1735.         };
  1736.         if((*cpnt++ & mask2) != mask2) {z++; break;}
  1737.       };
  1738.     };
  1739.       };
  1740.       /* z is 0 if all of the pixels used by the current box are already covered.
  1741.      No point in proceeding, so we just skip all further processing of this
  1742.      box. */
  1743.       if(!z) continue;
  1744.       /* Now we need to figure out whether we are looking at the top or the
  1745.      bottom of the square.  A simple cross product will tell us this.
  1746.      If the square is really distorted then this will not be accurate,
  1747.      but in such cases we would actually be seeing both sides at the same
  1748.      time.  We choose the vertex with the largest z component to
  1749.      take the cross product at.  */
  1750.       {
  1751.     int z1, z2 ,z3, z4;
  1752.     z1 = XPRD(j+row_offset,j,j+1);
  1753.     z2 = XPRD(j,j+1,j+1+row_offset);
  1754.     z3 = XPRD(j+1,j+row_offset+1,j+row_offset);
  1755.     z4 = XPRD(j+row_offset+1,j+row_offset,j);
  1756.     z=0;
  1757.     z += (z1 > 0 ? 1 : -1);
  1758.     z += (z2 > 0 ? 1 : -1);
  1759.     z += (z3 > 0 ? 1 : -1);
  1760.     z += (z4 > 0 ? 1 : -1);
  1761.     /* See if the box is uniformly one side or another. */
  1762.     if(z != 4 && z != -4) {
  1763. /* It isn't.  Now find the corner of the box with the largest z value that
  1764.    has already been plotted, and use the same style used for that node.  */
  1765.       k = -1000;
  1766.       x = -32768;
  1767.       if (nodes[j].z > x && nodes[j].style_used !=-1000) {
  1768.         k = nodes[j].style_used;
  1769.         x = nodes[j].z;
  1770.       };
  1771.       if (nodes[j+1].z > x && nodes[j+1].style_used !=-1000) {
  1772.         k = nodes[j+1].style_used;
  1773.         x = nodes[j+1].z;
  1774.       };
  1775.       if (nodes[j+row_offset+1].z > x && nodes[j+row_offset+1].style_used !=-1000) {
  1776.         k = nodes[j+row_offset+1].style_used;
  1777.         x = nodes[j+row_offset+1].z;
  1778.       };
  1779.       if (nodes[j+row_offset].z > x && nodes[j+row_offset].style_used !=-1000) {
  1780.         k = nodes[j+row_offset].style_used;
  1781.         x = nodes[j+row_offset].z;
  1782.       };
  1783.       if( k != -1000){
  1784.         z = 0; /* To defeat the logic to come.  */
  1785.         current_style = k;
  1786.         (*t->linetype)(current_style);
  1787.       };
  1788.     };
  1789.     /* If k == -1000 then no corner found.  I guess it does not matter.  */
  1790.       };
  1791.       if(z > 0 && current_style != plot_info[nplot].above_color) {
  1792.     current_style = plot_info[nplot].above_color;
  1793.     (*t->linetype)(current_style);
  1794.       };
  1795.       if(z < 0 && current_style != plot_info[nplot].below_color) {
  1796.     current_style = plot_info[nplot].below_color;
  1797.     (*t->linetype)(current_style);
  1798.       };
  1799.       xmin_hl = (sizeof(xleft) == 4 ? 0x7fffffff : 0x7fff ); 
  1800.       xmax_hl = 0;
  1801.       clip_move(nodes[j].x,nodes[j].y);
  1802.       clip_vector(nodes[j+1].x,nodes[j+1].y);
  1803.       clip_vector(nodes[j+row_offset+1].x,nodes[j+row_offset+1].y);
  1804.       clip_vector(nodes[j+row_offset].x,nodes[j+row_offset].y);
  1805.       clip_vector(nodes[j].x,nodes[j].y);
  1806.       nodes[j].style_used = current_style;
  1807.       nodes[j+1].style_used = current_style;
  1808.       nodes[j+row_offset+1].style_used = current_style;
  1809.       nodes[j+row_offset].style_used = current_style;
  1810.       MAYBE_LINEPOINT(j);
  1811.       MAYBE_LINEPOINT(j+1);
  1812.       MAYBE_LINEPOINT(j+row_offset+1);
  1813.       MAYBE_LINEPOINT(j+row_offset);
  1814.       if( xmin_hl < 0 || xmax_hl > XREDUCE(xright)-XREDUCE(xleft))
  1815.     int_error("Logic error #3 in hidden line",NO_CARET);
  1816.       /* now mark the area as being filled in the bitmap.  These coordinates
  1817.          have already been reduced. */
  1818.       if (xmin_hl < xmax_hl)
  1819.     for(j=xmin_hl;j<=xmax_hl;j++) {
  1820.       if (ymin_hl[j] == 0x7fff) 
  1821.         int_error("Logic error #2 in hidden line",NO_CARET);
  1822.       if(pnt[j] == 0) {
  1823.         pnt[j] = (short int *) alloc((unsigned long)y_malloc,"hidden");
  1824.         bzero(pnt[j],y_malloc);
  1825.       };
  1826.       if(ymin_hl[j] < 0 || ymax_hl[j] > YREDUCE(ytop)-YREDUCE(ybot))
  1827.         int_error("Logic error #1 in hidden line",NO_CARET);
  1828. /* this shift is wordsize dependent */
  1829.       indx1 = ymin_hl[j] >> 4;
  1830.       indx2 = ymax_hl[j] >> 4;
  1831.       mask1 = 0xffff << (ymin_hl[j] & 0xf);
  1832.       mask2 = 0xffff >> (0xf-(ymax_hl[j] & 0xf));
  1833.       cpnt = pnt[j] + indx1;
  1834.       if(indx1 == indx2){
  1835.         *cpnt |= (mask1 & mask2);
  1836.       } else {
  1837.         *cpnt++ |= mask1;
  1838.         k = indx1+1;
  1839.         while (k != indx2) {
  1840.           *cpnt++ = 0xffff; 
  1841.           k++;
  1842.         };
  1843.         *cpnt |= mask2;
  1844.       };
  1845.       ymin_hl[j]=0x7fff; 
  1846.       ymax_hl[j]=0;
  1847.     };
  1848.     };
  1849.   };
  1850.   free(nodes);
  1851.   free(boxlist);
  1852.   free(plot_info);
  1853. }
  1854.  
  1855. #endif /* not LITE */
  1856.  
  1857. static plot3d_lines(plot)
  1858.     struct surface_points *plot;
  1859. {
  1860.     int i;
  1861.     int x,y;                /* point in terminal coordinates */
  1862.     struct iso_curve *icrvs = plot->iso_crvs;
  1863.     struct coordinate GPHUGE *points;
  1864.  
  1865. #ifndef LITE
  1866. /* These are handled elsewhere.  */
  1867.     if (plot->has_grid_topology && hidden3d)
  1868.     return(0);
  1869. #endif /* not LITE */
  1870.  
  1871.     while (icrvs) {
  1872.  
  1873.     for (i = 0, points = icrvs->points; i < icrvs->p_count; i++) {
  1874.         if (real_z_max3d<points[i].z)
  1875.         real_z_max3d=points[i].z;
  1876.         if (real_z_min3d>points[i].z)
  1877.         real_z_min3d=points[i].z;
  1878.  
  1879.         map3d_xy(points[i].x, points[i].y, points[i].z, &x, &y);
  1880.  
  1881.         if (i > 0)
  1882.         clip_vector(x,y);
  1883.         else
  1884.         clip_move(x,y);
  1885.     }
  1886.  
  1887.     icrvs = icrvs->next;
  1888.     }
  1889. }
  1890.  
  1891. /* plot3d_points:
  1892.  * Plot the surfaces in POINTSTYLE style
  1893.  */
  1894. static plot3d_points(plot)
  1895.     struct surface_points *plot;
  1896. {
  1897.     int i,x,y;
  1898.     struct termentry *t = &term_tbl[term];
  1899.     struct iso_curve *icrvs = plot->iso_crvs;
  1900.  
  1901.     while ( icrvs ) {
  1902.     struct coordinate GPHUGE *points = icrvs->points;
  1903.  
  1904.     for (i = 0; i < icrvs->p_count; i++) {
  1905.         if (real_z_max3d<points[i].z)
  1906.         real_z_max3d=points[i].z;
  1907.         if (real_z_min3d>points[i].z)
  1908.         real_z_min3d=points[i].z;
  1909.  
  1910.         map3d_xy(points[i].x, points[i].y, points[i].z, &x, &y);
  1911.  
  1912.         if (!clip_point(x,y))
  1913.         (*t->point)(x,y, plot->point_type);
  1914.     }
  1915.  
  1916.     icrvs = icrvs->next;
  1917.     }
  1918. }
  1919.  
  1920. /* plot3d_dots:
  1921.  * Plot the surfaces in DOTS style
  1922.  */
  1923. static plot3d_dots(plot)
  1924.     struct surface_points *plot;
  1925. {
  1926.     int i,x,y;
  1927.     struct termentry *t = &term_tbl[term];
  1928.     struct iso_curve *icrvs = plot->iso_crvs;
  1929.  
  1930.     while ( icrvs ) {
  1931.     struct coordinate GPHUGE *points = icrvs->points;
  1932.  
  1933.         for (i = 0; i < icrvs->p_count; i++) {
  1934.         if (real_z_max3d<points[i].z)
  1935.         real_z_max3d=points[i].z;
  1936.         if (real_z_min3d>points[i].z)
  1937.             real_z_min3d=points[i].z;
  1938.  
  1939.             map3d_xy(points[i].x, points[i].y, points[i].z, &x, &y);
  1940.  
  1941.             if (!clip_point(x,y))
  1942.         (*t->point)(x,y, -1);
  1943.         }
  1944.  
  1945.     icrvs = icrvs->next;
  1946.     }
  1947. }
  1948.  
  1949. /* cntr3d_impulses:
  1950.  * Plot a surface contour in IMPULSES style
  1951.  */
  1952. static cntr3d_impulses(cntr, plot)
  1953.     struct gnuplot_contours *cntr;
  1954.     struct surface_points *plot;
  1955. {
  1956.     int i;                /* point index */
  1957.     int x,y,x0,y0;            /* point in terminal coordinates */
  1958.  
  1959.     if (draw_contour == CONTOUR_SRF || draw_contour == CONTOUR_BOTH) {
  1960.     for (i = 0; i < cntr->num_pts; i++) {
  1961.         if (real_z_max3d<cntr->coords[i].z)
  1962.         real_z_max3d=cntr->coords[i].z;
  1963.         if (real_z_min3d>cntr->coords[i].z)
  1964.         real_z_min3d=cntr->coords[i].z;
  1965.  
  1966.         map3d_xy(cntr->coords[i].x, cntr->coords[i].y, cntr->coords[i].z,
  1967.              &x, &y);
  1968.         map3d_xy(cntr->coords[i].x, cntr->coords[i].y, z_min3d,
  1969.              &x0, &y0);
  1970.  
  1971.         clip_move(x0,y0);
  1972.         clip_vector(x,y);
  1973.     }
  1974.     }
  1975.     else
  1976.     cntr3d_points(cntr, plot);   /* Must be on base grid, so do points. */
  1977. }
  1978.  
  1979. /* cntr3d_lines:
  1980.  * Plot a surface contour in LINES style
  1981.  */
  1982. static cntr3d_lines(cntr)
  1983.     struct gnuplot_contours *cntr;
  1984. {
  1985.     int i;                /* point index */
  1986.     int x,y;                /* point in terminal coordinates */
  1987.  
  1988.     if (draw_contour == CONTOUR_SRF || draw_contour == CONTOUR_BOTH) {
  1989.     for (i = 0; i < cntr->num_pts; i++) {
  1990.         if (real_z_max3d<cntr->coords[i].z)
  1991.         real_z_max3d=cntr->coords[i].z;
  1992.         if (real_z_min3d>cntr->coords[i].z)
  1993.         real_z_min3d=cntr->coords[i].z;
  1994.  
  1995.             map3d_xy(cntr->coords[i].x, cntr->coords[i].y, cntr->coords[i].z,
  1996.                  &x, &y);
  1997.  
  1998.              if (i > 0) {
  1999.                  clip_vector(x,y);
  2000.                  if(i == 1) suppressMove = TRUE;
  2001.              } else {
  2002.                  clip_move(x,y);
  2003.              }
  2004.         }
  2005.     }
  2006.      suppressMove = FALSE;  /* beginning a new contour level, so moveto() required */
  2007.  
  2008.     if (draw_contour == CONTOUR_BASE || draw_contour == CONTOUR_BOTH) {
  2009.     for (i = 0; i < cntr->num_pts; i++) {
  2010.         if (real_z_max3d<cntr->coords[i].z)
  2011.         real_z_max3d=cntr->coords[i].z;
  2012.         if (real_z_min3d>cntr->coords[i].z)
  2013.         real_z_min3d=cntr->coords[i].z;
  2014.  
  2015.             map3d_xy(cntr->coords[i].x, cntr->coords[i].y, z_min3d,
  2016.                  &x, &y);
  2017.  
  2018.              if (i > 0) {
  2019.                  clip_vector(x,y);
  2020.                  if(i == 1) suppressMove = TRUE;
  2021.              } else {
  2022.                  clip_move(x,y);
  2023.              }
  2024.          }
  2025.      }
  2026.      suppressMove = FALSE;  /* beginning a new contour level, so moveto() required */
  2027. }
  2028.  
  2029. /* cntr3d_points:
  2030.  * Plot a surface contour in POINTSTYLE style
  2031.  */
  2032. static cntr3d_points(cntr, plot)
  2033.     struct gnuplot_contours *cntr;
  2034.     struct surface_points *plot;
  2035. {
  2036.     int i;
  2037.     int x,y;
  2038.     struct termentry *t = &term_tbl[term];
  2039.  
  2040.     if (draw_contour == CONTOUR_SRF || draw_contour == CONTOUR_BOTH) {
  2041.     for (i = 0; i < cntr->num_pts; i++) {
  2042.         if (real_z_max3d<cntr->coords[i].z)
  2043.         real_z_max3d=cntr->coords[i].z;
  2044.         if (real_z_min3d>cntr->coords[i].z)
  2045.         real_z_min3d=cntr->coords[i].z;
  2046.  
  2047.             map3d_xy(cntr->coords[i].x, cntr->coords[i].y, cntr->coords[i].z,
  2048.                  &x, &y);
  2049.  
  2050.         if (!clip_point(x,y))
  2051.         (*t->point)(x,y, plot->point_type);
  2052.         }
  2053.     }
  2054.  
  2055.     if (draw_contour == CONTOUR_BASE || draw_contour == CONTOUR_BOTH) {
  2056.     for (i = 0; i < cntr->num_pts; i++) {
  2057.         if (real_z_max3d<cntr->coords[i].z)
  2058.         real_z_max3d=cntr->coords[i].z;
  2059.         if (real_z_min3d>cntr->coords[i].z)
  2060.         real_z_min3d=cntr->coords[i].z;
  2061.  
  2062.             map3d_xy(cntr->coords[i].x, cntr->coords[i].y, z_min3d,
  2063.                  &x, &y);
  2064.  
  2065.         if (!clip_point(x,y))
  2066.         (*t->point)(x,y, plot->point_type);
  2067.         }
  2068.     }
  2069. }
  2070.  
  2071. /* cntr3d_dots:
  2072.  * Plot a surface contour in DOTS style
  2073.  */
  2074. static cntr3d_dots(cntr)
  2075.     struct gnuplot_contours *cntr;
  2076. {
  2077.     int i;
  2078.     int x,y;
  2079.     struct termentry *t = &term_tbl[term];
  2080.  
  2081.     if (draw_contour == CONTOUR_SRF || draw_contour == CONTOUR_BOTH) {
  2082.     for (i = 0; i < cntr->num_pts; i++) {
  2083.         if (real_z_max3d<cntr->coords[i].z)
  2084.         real_z_max3d=cntr->coords[i].z;
  2085.         if (real_z_min3d>cntr->coords[i].z)
  2086.         real_z_min3d=cntr->coords[i].z;
  2087.  
  2088.             map3d_xy(cntr->coords[i].x, cntr->coords[i].y, cntr->coords[i].z,
  2089.                  &x, &y);
  2090.  
  2091.         if (!clip_point(x,y))
  2092.         (*t->point)(x,y, -1);
  2093.         }
  2094.     }
  2095.  
  2096.     if (draw_contour == CONTOUR_BASE || draw_contour == CONTOUR_BOTH) {
  2097.     for (i = 0; i < cntr->num_pts; i++) {
  2098.         if (real_z_max3d<cntr->coords[i].z)
  2099.         real_z_max3d=cntr->coords[i].z;
  2100.         if (real_z_min3d>cntr->coords[i].z)
  2101.         real_z_min3d=cntr->coords[i].z;
  2102.  
  2103.             map3d_xy(cntr->coords[i].x, cntr->coords[i].y, z_min3d,
  2104.                  &x, &y);
  2105.  
  2106.         if (!clip_point(x,y))
  2107.         (*t->point)(x,y, -1);
  2108.         }
  2109.     }
  2110. }
  2111.  
  2112. #ifdef THINK_C
  2113. update_extrema_pts(ix, iy, min_sx_x, min_sx_y, min_sy_x, min_sy_y,
  2114.               x, y)
  2115. #else
  2116. static update_extrema_pts(ix, iy, min_sx_x, min_sx_y, min_sy_x, min_sy_y,
  2117.               x, y)
  2118. #endif
  2119.     int ix, iy, *min_sx_x, *min_sx_y, *min_sy_x, *min_sy_y;
  2120.     double x, y;
  2121. {
  2122.  
  2123.     if (*min_sx_x > ix + 2 ||         /* find (bottom) left corner of grid */
  2124.     (abs(*min_sx_x - ix) <= 2 && *min_sx_y > iy)) {
  2125.     *min_sx_x = ix;
  2126.     *min_sx_y = iy;
  2127.     min_sx_ox = x;
  2128.     min_sx_oy = y;
  2129.     }
  2130.     if (*min_sy_y > iy + 2 ||         /* find bottom (right) corner of grid */
  2131.     (abs(*min_sy_y - iy) <= 2 && *min_sy_x < ix)) {
  2132.     *min_sy_x = ix;
  2133.     *min_sy_y = iy;
  2134.     min_sy_ox = x;
  2135.     min_sy_oy = y;
  2136.     }
  2137. }
  2138.  
  2139. #endif /* THINK_C_3 */
  2140.  
  2141.  
  2142. #ifdef THINK_C_4
  2143.  
  2144. /* Draw the bottom grid for the parametric case. */
  2145. static draw_parametric_grid(plot)
  2146.     struct surface_points *plot;
  2147. {
  2148.     int i,ix,iy,            /* point in terminal coordinates */
  2149.     min_sx_x = 10000,min_sx_y = 10000,min_sy_x = 10000,min_sy_y = 10000,
  2150.         grid_iso_1 = plot->plot_type == DATA3D && plot->has_grid_topology ?
  2151.                     plot->iso_crvs->p_count : iso_samples_1,
  2152.         grid_iso_2 = plot->plot_type == DATA3D && plot->has_grid_topology ?
  2153.                     plot->num_iso_read : iso_samples_2;
  2154.     double x,y,dx,dy;
  2155.  
  2156.     if (grid && plot->has_grid_topology) {
  2157.  
  2158.     /* fix grid lines to tic marks, D. Taber, 02-01-93 */
  2159.     if(xtics && xticdef.type == TIC_SERIES) {
  2160.         dx = xticdef.def.series.incr;
  2161.         x = xticdef.def.series.start;
  2162.         grid_iso_1 = 1 + (xticdef.def.series.end - x) / dx;
  2163.     } else {
  2164.         x = x_min3d;
  2165.     dx = (x_max3d-x_min3d) / (grid_iso_1-1);
  2166.     }
  2167.  
  2168.     if(ytics && yticdef.type == TIC_SERIES) {
  2169.         dy = yticdef.def.series.incr;
  2170.         y = yticdef.def.series.start;
  2171.         grid_iso_2 = 1 + (yticdef.def.series.end - y) / dy;
  2172.     } else {
  2173.         y = y_min3d;
  2174.     dy = (y_max3d-y_min3d) / (grid_iso_2-1);
  2175.     }
  2176.  
  2177.     for (i = 0; i < grid_iso_2; i++) {
  2178.             if (i == 0 || i == grid_iso_2-1)            
  2179.             setlinestyle(-2);
  2180.         else
  2181.             setlinestyle(-1);
  2182.         map3d_xy(x_min3d, y, z_min3d, &ix, &iy);
  2183.         clip_move(ix,iy);
  2184.         update_extrema_pts(ix,iy,&min_sx_x,&min_sx_y,
  2185.                    &min_sy_x,&min_sy_y,x_min3d,y);
  2186.  
  2187.         map3d_xy(x_max3d, y, z_min3d, &ix, &iy);
  2188.         clip_vector(ix,iy);
  2189.         update_extrema_pts(ix,iy,&min_sx_x,&min_sx_y,
  2190.                    &min_sy_x,&min_sy_y,x_max3d,y);
  2191.  
  2192.         y += dy;
  2193.     }
  2194.  
  2195.     for (i = 0; i < grid_iso_1; i++) {
  2196.             if (i == 0 || i == grid_iso_1-1)
  2197.             setlinestyle(-2);
  2198.         else
  2199.             setlinestyle(-1);
  2200.         map3d_xy(x, y_min3d, z_min3d, &ix, &iy);
  2201.         clip_move(ix,iy);
  2202.         update_extrema_pts(ix,iy,&min_sx_x,&min_sx_y,
  2203.                    &min_sy_x,&min_sy_y,x,y_min3d);
  2204.  
  2205.         map3d_xy(x, y_max3d, z_min3d, &ix, &iy);
  2206.         clip_vector(ix,iy);
  2207.         update_extrema_pts(ix,iy,&min_sx_x,&min_sx_y,
  2208.                    &min_sy_x,&min_sy_y,x,y_max3d);
  2209.  
  2210.         x += dx;
  2211.     }
  2212.     }
  2213.     else {
  2214.     setlinestyle(-2);
  2215.  
  2216.     map3d_xy(x_min3d, y_min3d, z_min3d, &ix, &iy);
  2217.     clip_move(ix,iy);
  2218.     update_extrema_pts(ix,iy,&min_sx_x,&min_sx_y,
  2219.                &min_sy_x,&min_sy_y,x_min3d,y_min3d);
  2220.  
  2221.     map3d_xy(x_max3d, y_min3d, z_min3d, &ix, &iy);
  2222.     clip_vector(ix,iy);
  2223.     update_extrema_pts(ix,iy,&min_sx_x,&min_sx_y,
  2224.                &min_sy_x,&min_sy_y,x_max3d,y_min3d);
  2225.  
  2226.     map3d_xy(x_max3d, y_max3d, z_min3d, &ix, &iy);
  2227.     clip_vector(ix,iy);
  2228.     update_extrema_pts(ix,iy,&min_sx_x,&min_sx_y,
  2229.                &min_sy_x,&min_sy_y,x_max3d,y_max3d);
  2230.  
  2231.     map3d_xy(x_min3d, y_max3d, z_min3d, &ix, &iy);
  2232.     clip_vector(ix,iy);
  2233.     update_extrema_pts(ix,iy,&min_sx_x,&min_sx_y,
  2234.                &min_sy_x,&min_sy_y,x_min3d,y_max3d);
  2235.  
  2236.  
  2237.     map3d_xy(x_min3d, y_min3d, z_min3d, &ix, &iy);
  2238.     clip_vector(ix,iy);
  2239.     }
  2240. }
  2241.  
  2242. /* Draw the bottom grid for non parametric case. */
  2243. static draw_non_param_grid(plot)
  2244.     struct surface_points *plot;
  2245. {
  2246.     int i,is_boundary=TRUE,crv_count=0,
  2247.     x,y,                /* point in terminal coordinates */
  2248.     min_sx_x = 10000,min_sx_y = 10000,min_sy_x = 10000,min_sy_y = 10000,
  2249.         grid_iso = plot->plot_type == DATA3D && plot->has_grid_topology ?
  2250.                     plot->num_iso_read : iso_samples_2;
  2251.     struct iso_curve *icrvs = plot->iso_crvs;
  2252.  
  2253.     while ( icrvs ) {
  2254.     struct coordinate GPHUGE *points = icrvs->points;
  2255.     int saved_hidden_active = hidden_active;
  2256.     int z1 = map3d_z(points[0].x, points[0].y, 0.0),
  2257.            z2 = map3d_z(points[icrvs->p_count-1].x,
  2258.                             points[icrvs->p_count-1].y, 0.0);
  2259.  
  2260.     for (i = 0; i < icrvs->p_count; i += icrvs->p_count-1) {
  2261.         map3d_xy(points[i].x, points[i].y, z_min3d, &x, &y);
  2262.         if (is_boundary) {
  2263.         setlinestyle(-2);
  2264.         }
  2265.         else {
  2266.             setlinestyle(-1);
  2267.         }
  2268.  
  2269.         if (i > 0) {
  2270.             clip_vector(x,y);
  2271.         }
  2272.         else {
  2273.             clip_move(x,y);
  2274.         }
  2275.  
  2276.         if (draw_surface &&
  2277.             is_boundary &&
  2278.             (i == 0 || i == icrvs->p_count-1)) {
  2279.             int x1,y1;            /* point in terminal coordinates */
  2280.  
  2281.         /* Draw a vertical line to surface corner from grid corner. */
  2282.             map3d_xy(points[i].x, points[i].y, points[i].z, &x1, &y1);
  2283. #ifndef LITE
  2284.             if (hidden3d) {
  2285.             if ((i == 0 && z1 > z2) ||
  2286.                 (i == icrvs->p_count-1 && z2 > z1)) {
  2287.                 hidden_active = FALSE; /* This one is always visible. */
  2288.             }                
  2289.             }
  2290. #endif /* not LITE */
  2291.             clip_vector(x1,y1);
  2292.             clip_move(x,y);
  2293.         hidden_active = saved_hidden_active;
  2294.         update_extrema_pts(x,y,&min_sx_x,&min_sx_y, &min_sy_x,&min_sy_y,
  2295.                    points[i].x,points[i].y);
  2296.         }
  2297.     }
  2298.  
  2299.     if (grid) {
  2300.         crv_count++;
  2301.         icrvs = icrvs->next;
  2302.         is_boundary = crv_count == grid_iso - 1 ||
  2303.               crv_count == grid_iso ||
  2304.               (icrvs && icrvs->next == NULL);
  2305.     }
  2306.     else {
  2307.         switch (crv_count++) {
  2308.         case 0:
  2309.             for (i = 0; i < grid_iso - 1; i++)
  2310.             icrvs = icrvs->next;
  2311.             break;
  2312.         case 1:
  2313.             icrvs = icrvs->next;
  2314.             break;
  2315.         case 2:
  2316.             while (icrvs->next)
  2317.             icrvs = icrvs->next;
  2318.             break;
  2319.         case 3:
  2320.             icrvs = NULL;
  2321.             break;
  2322.         }
  2323.         }
  2324.     }
  2325.     if(hidden3d){
  2326.       struct iso_curve *lcrvs = plot->iso_crvs;
  2327.       struct coordinate GPHUGE *points, GPHUGE *lpoints;
  2328.       icrvs = lcrvs;
  2329.       while(lcrvs->next) lcrvs = lcrvs->next;
  2330.       points = icrvs->points;
  2331.       lpoints = lcrvs->points;
  2332.       is_boundary = TRUE;
  2333.       for (i = 0; i < icrvs->p_count; i += (grid ? 1 : icrvs->p_count - 1)) {
  2334.     if ((i == 0) || (i == icrvs->p_count - 1)) {
  2335.       setlinestyle(-2);
  2336.     }
  2337.     else {
  2338.       setlinestyle(-1);
  2339.     }
  2340.     map3d_xy(points[i].x, points[i].y, z_min3d, &x, &y);
  2341.     clip_move(x, y);
  2342.     map3d_xy(lpoints[i].x, lpoints[i].y, z_min3d, &x, &y);
  2343.     clip_vector(x, y);
  2344.       };
  2345.     };
  2346. }
  2347.  
  2348. /* Draw the bottom grid that hold the tic marks for 3d surface. */
  2349. #ifdef THINK_C
  2350. draw_bottom_grid(plot, min_z, max_z)
  2351. #else
  2352. static draw_bottom_grid(plot, min_z, max_z)
  2353. #endif
  2354.     struct surface_points *plot;
  2355.     double min_z, max_z;
  2356. {
  2357.     int x,y;    /* point in terminal coordinates */
  2358.     double xtic,ytic,ztic;
  2359.     struct termentry *t = &term_tbl[term];
  2360.  
  2361.     xtic = make_3dtics(x_min3d,x_max3d,'x',is_log_x,base_log_x);
  2362.     ytic = make_3dtics(y_min3d,y_max3d,'y',is_log_y,base_log_y);
  2363.     ztic = make_3dtics(min_z,max_z,'z',is_log_z,base_log_z);
  2364.  
  2365.     if (draw_border)
  2366.     if (parametric || !plot->has_grid_topology)
  2367.         draw_parametric_grid(plot);
  2368.     else
  2369.         draw_non_param_grid(plot);
  2370.  
  2371.     setlinestyle(-2); /* border linetype */
  2372.  
  2373. /* label x axis tics */
  2374.     if (xtics && xtic > 0.0) {
  2375.         switch (xticdef.type) {
  2376.             case TIC_COMPUTED:
  2377.          if (x_min3d < x_max3d)
  2378.             draw_3dxtics(xtic * floor(x_min3d/xtic),
  2379.                      xtic,
  2380.                      xtic * ceil(x_max3d/xtic),
  2381.                      min_sy_oy);
  2382.                 else
  2383.             draw_3dxtics(xtic * floor(x_max3d/xtic),
  2384.                      xtic,
  2385.                      xtic * ceil(x_min3d/xtic),
  2386.                      min_sy_oy);
  2387.             break;
  2388.         case TIC_MONTH:
  2389.         draw_month_3dxtics(min_sy_oy);
  2390.         break;
  2391.         case TIC_DAY:
  2392.         draw_day_3dxtics(min_sy_oy);
  2393.         break;
  2394.         case TIC_SERIES:
  2395.         draw_series_3dxtics(xticdef.def.series.start, 
  2396.                     xticdef.def.series.incr, 
  2397.                     xticdef.def.series.end,
  2398.                     min_sy_oy);
  2399.         break;
  2400.         case TIC_USER:
  2401.         draw_set_3dxtics(xticdef.def.user,
  2402.                  min_sy_oy);
  2403.         break;
  2404.             default:
  2405.             (*t->text)();
  2406.             (void) fflush(outfile);
  2407.             int_error("unknown tic type in xticdef in do_3dplot", NO_CARET);
  2408.             break;        /* NOTREACHED */
  2409.         }
  2410.     }
  2411. /* label y axis tics */
  2412.     if (ytics && (ytic > 0.0)) {
  2413.         switch (yticdef.type) {
  2414.             case TIC_COMPUTED:
  2415.          if (y_min3d < y_max3d) {
  2416.             draw_3dytics(ytic * floor(y_min3d/ytic),
  2417.                      ytic,
  2418.                      ytic * ceil(y_max3d/ytic),
  2419.                      min_sy_ox);
  2420.          }else{
  2421.             draw_3dytics(ytic * floor(y_max3d/ytic),
  2422.                      ytic,
  2423.                      ytic * ceil(y_min3d/ytic),
  2424.                      min_sy_ox);
  2425.         }
  2426.             break;
  2427.         case TIC_MONTH:
  2428.         draw_month_3dytics(min_sy_ox);
  2429.         break;
  2430.         case TIC_DAY:
  2431.         draw_day_3dytics(min_sy_ox);
  2432.         break;
  2433.         case TIC_SERIES:
  2434.         draw_series_3dytics(yticdef.def.series.start, 
  2435.                     yticdef.def.series.incr, 
  2436.                     yticdef.def.series.end,
  2437.                     min_sy_ox);
  2438.         break;
  2439.         case TIC_USER:
  2440.         draw_set_3dytics(yticdef.def.user,
  2441.                  min_sy_ox);
  2442.         break;
  2443.             default:
  2444.             (*t->text)();
  2445.             (void) fflush(outfile);
  2446.             int_error("unknown tic type in yticdef in do_3dplot", NO_CARET);
  2447.             break;        /* NOTREACHED */
  2448.         }
  2449.     }
  2450. /* label z axis tics */
  2451.     if (ztics && ztic > 0.0 && (draw_surface ||
  2452.                 draw_contour == CONTOUR_SRF ||
  2453.                 draw_contour == CONTOUR_BOTH)) {
  2454.         switch (zticdef.type) {
  2455.             case TIC_COMPUTED:
  2456.          if (min_z < max_z)
  2457.             draw_3dztics(ztic * floor(min_z/ztic),
  2458.                      ztic,
  2459.                      ztic * ceil(max_z/ztic),
  2460.                  min_sx_ox,
  2461.                      min_sx_oy,
  2462.                      min_z,
  2463.                  max_z);
  2464.                 else
  2465.             draw_3dztics(ztic * floor(max_z/ztic),
  2466.                      ztic,
  2467.                      ztic * ceil(min_z/ztic),
  2468.                      min_sx_ox,
  2469.                  min_sx_oy,
  2470.                      max_z,
  2471.                  min_z);
  2472.             break;
  2473.         case TIC_MONTH:
  2474.         draw_month_3dztics(min_sx_ox,min_sx_oy,min_z,max_z);
  2475.         break;
  2476.         case TIC_DAY:
  2477.         draw_day_3dztics(min_sx_ox,min_sx_oy,min_z,max_z);
  2478.         break;
  2479.         case TIC_SERIES:
  2480.         draw_series_3dztics(zticdef.def.series.start, 
  2481.                     zticdef.def.series.incr, 
  2482.                     zticdef.def.series.end,
  2483.                     min_sx_ox,
  2484.                     min_sx_oy,
  2485.                     min_z,
  2486.                     max_z);
  2487.  
  2488.         break;
  2489.         case TIC_USER:
  2490.         draw_set_3dztics(zticdef.def.user,
  2491.                  min_sx_ox,
  2492.                      min_sx_oy,
  2493.                      min_z,
  2494.                  max_z);
  2495.         break;
  2496.             default:
  2497.             (*t->text)();
  2498.             (void) fflush(outfile);
  2499.             int_error("unknown tic type in zticdef in do_3dplot", NO_CARET);
  2500.             break;        /* NOTREACHED */
  2501.         }
  2502.     }
  2503.  
  2504. /* PLACE XLABEL - along the middle grid X axis */
  2505.     if (strlen(xlabel) > 0) {
  2506.        int x1,y1;
  2507.        double step = apx_eq( min_sy_oy, y_min3d ) ?    (y_max3d-y_min3d)/4
  2508.                               : (y_min3d-y_max3d)/4;
  2509.            map3d_xy((x_min3d+x_max3d)/2,min_sy_oy-step, z_min3d,&x1,&y1);
  2510.        x1 += xlabel_xoffset * t->h_char;
  2511.        y1 += xlabel_yoffset * t->v_char;
  2512.        if ((*t->justify_text)(CENTRE))
  2513.         clip_put_text(x1,y1,xlabel);
  2514.        else
  2515.         clip_put_text(x1 - strlen(xlabel)*(t->h_char)/2,y1,xlabel);
  2516.     }
  2517.  
  2518. /* PLACE YLABEL - along the middle grid Y axis */
  2519.     if (strlen(ylabel) > 0) {
  2520.        int x1,y1;
  2521.        double step = apx_eq( min_sy_ox, x_min3d ) ?    (x_max3d-x_min3d)/4
  2522.                               : (x_min3d-x_max3d)/4;
  2523.            map3d_xy(min_sy_ox-step,(y_min3d+y_max3d)/2,z_min3d,&x1,&y1);
  2524.        x1 += ylabel_xoffset * t->h_char;
  2525.        y1 += ylabel_yoffset * t->v_char;
  2526.        if ((*t->justify_text)(CENTRE))
  2527.         clip_put_text(x1,y1,ylabel);
  2528.        else
  2529.         clip_put_text(x1 - strlen(ylabel)*(t->h_char)/2,y1,ylabel);
  2530.     }
  2531.  
  2532. /* PLACE ZLABEL - along the middle grid Z axis */
  2533.     if (strlen(zlabel) > 0 &&
  2534.         (draw_surface ||
  2535.      draw_contour == CONTOUR_SRF ||
  2536.      draw_contour == CONTOUR_BOTH)) {
  2537.            map3d_xy(min_sx_ox,min_sx_oy,max_z + (max_z-min_z)/4, &x, &y);
  2538.  
  2539.        x += zlabel_xoffset * t->h_char;
  2540.        y += zlabel_yoffset * t->v_char;
  2541.        if ((*t->justify_text)(CENTRE))
  2542.         clip_put_text(x,y,zlabel);
  2543.        else
  2544.         clip_put_text(x - strlen(zlabel)*(t->h_char)/2,y,zlabel);
  2545.     }
  2546. }
  2547.  
  2548. /* DRAW_3DXTICS: draw a regular tic series, x axis */
  2549. static draw_3dxtics(start, incr, end, ypos)
  2550.     double start, incr, end, ypos; /* tic series definition */
  2551.         /* assume start < end, incr > 0 */
  2552. {
  2553.     double ticplace;
  2554.     int ltic;        /* for mini log tics */
  2555.     double lticplace;    /* for mini log tics */
  2556.  
  2557.     end = end + SIGNIF*incr; 
  2558.  
  2559.     for (ticplace = start; ticplace <= end; ticplace +=incr) {
  2560.         if (ticplace < start || ticplace > end) continue;
  2561.         xtick3d(ticplace, xformat, incr, 1.0, ypos);
  2562.         if (is_log_x && incr == 1.0) {
  2563.             /* add mini-ticks to log scale ticmarks */
  2564.             for (ltic = 2; ltic < (int)base_log_x; ltic++) {
  2565.                 lticplace = ticplace+log((double)ltic)/log_base_log_x;
  2566.                 xtick3d(lticplace, "\0", incr, 0.5, ypos);
  2567.             }
  2568.         }
  2569.     }
  2570. }
  2571.  
  2572. /* DRAW_3DYTICS: draw a regular tic series, y axis */
  2573. static draw_3dytics(start, incr, end, xpos)
  2574.     double start, incr, end, xpos; /* tic series definition */
  2575.         /* assume start < end, incr > 0 */
  2576. {
  2577.     double ticplace;
  2578.     int ltic;        /* for mini log tics */
  2579.     double lticplace;    /* for mini log tics */
  2580.  
  2581.     end = end + SIGNIF*incr; 
  2582.  
  2583.     for (ticplace = start; ticplace <= end; ticplace +=incr) {
  2584.         if (ticplace < start || ticplace > end) continue;
  2585.         ytick3d(ticplace, yformat, incr, 1.0, xpos);
  2586.         if (is_log_y && incr == 1.0) {
  2587.             /* add mini-ticks to log scale ticmarks */
  2588.             for (ltic = 2; ltic < (int)base_log_y; ltic++) {
  2589.                 lticplace = ticplace+log((double)ltic)/log_base_log_y;
  2590.                 ytick3d(lticplace, "\0", incr, 0.5, xpos);
  2591.             }
  2592.         }
  2593.     }
  2594. }
  2595.  
  2596. /* DRAW_3DZTICS: draw a regular tic series, z axis */
  2597. static draw_3dztics(start, incr, end, xpos, ypos, z_min, z_max)
  2598.     double start, incr, end, xpos, ypos, z_min, z_max;
  2599.         /* assume start < end, incr > 0 */
  2600. {
  2601.     int x, y;
  2602.     double ticplace;
  2603.     int ltic;        /* for mini log tics */
  2604.     double lticplace;    /* for mini log tics */
  2605.  
  2606.     end = end + SIGNIF*incr; 
  2607.  
  2608.     for (ticplace = start; ticplace <= end; ticplace +=incr) {
  2609.         if (ticplace < start || ticplace > end) continue;
  2610.  
  2611.         ztick3d(ticplace, zformat, incr, 1.0, xpos, ypos);
  2612.         if (is_log_z && incr == 1.0) {
  2613.             /* add mini-ticks to log scale ticmarks */
  2614.             for (ltic = 2; ltic < (int)base_log_z; ltic++) {
  2615.                 lticplace = ticplace+log((double)ltic)/log_base_log_z;
  2616.                 ztick3d(lticplace, "\0", incr, 0.5, xpos, ypos);
  2617.             }
  2618.         }
  2619.     }
  2620.  
  2621.     /* Make sure the vertical line is fully drawn. */
  2622.     setlinestyle(-2);    /* axis line type */
  2623.  
  2624.     map3d_xy(xpos, ypos, z_min3d, &x, &y);
  2625.     clip_move(x,y);
  2626.     map3d_xy(xpos, ypos, min(end,z_max)+(is_log_z ? incr : 0.0), &x, &y);
  2627.     clip_vector(x,y);
  2628.  
  2629.     setlinestyle(-1); /* border linetype */
  2630. }
  2631.  
  2632. /* DRAW_SERIES_3DXTICS: draw a user tic series, x axis */
  2633. static draw_series_3dxtics(start, incr, end, ypos)
  2634.         double start, incr, end, ypos; /* tic series definition */
  2635.         /* assume start < end, incr > 0 */
  2636. {
  2637.     double ticplace, place;
  2638.     double ticmin, ticmax;    /* for checking if tic is almost inrange */
  2639.     double spacing = is_log_x ? log(incr)/log_base_log_x : incr;
  2640.  
  2641.     if (end == VERYLARGE)
  2642.         end = max(CheckLog(is_log_x, base_log_x, x_min3d),
  2643.               CheckLog(is_log_x, base_log_x, x_max3d));
  2644.     else
  2645.       /* limit to right side of plot */
  2646.       end = min(end, max(CheckLog(is_log_x, base_log_x, x_min3d),
  2647.                  CheckLog(is_log_x, base_log_x, x_max3d)));
  2648.  
  2649.     /* to allow for rounding errors */
  2650.     ticmin = min(x_min3d,x_max3d) - SIGNIF*incr;
  2651.     ticmax = max(x_min3d,x_max3d) + SIGNIF*incr;
  2652.     end = end + SIGNIF*incr; 
  2653.  
  2654.     for (ticplace = start; ticplace <= end; ticplace +=incr) {
  2655.         place = (is_log_x ? log(ticplace)/log_base_log_x : ticplace);
  2656.         if ( inrange(place,ticmin,ticmax) )
  2657.          xtick3d(place, xformat, spacing, 1.0, ypos);
  2658.     }
  2659. }
  2660.  
  2661. /* DRAW_SERIES_3DYTICS: draw a user tic series, y axis */
  2662. static draw_series_3dytics(start, incr, end, xpos)
  2663.         double start, incr, end, xpos; /* tic series definition */
  2664.         /* assume start < end, incr > 0 */
  2665. {
  2666.     double ticplace, place;
  2667.     double ticmin, ticmax;    /* for checking if tic is almost inrange */
  2668.     double spacing = is_log_y ? log(incr)/log_base_log_y : incr;
  2669.  
  2670.     if (end == VERYLARGE)
  2671.         end = max(CheckLog(is_log_y, base_log_y, y_min3d),
  2672.               CheckLog(is_log_y, base_log_y, y_max3d));
  2673.     else
  2674.       /* limit to right side of plot */
  2675.       end = min(end, max(CheckLog(is_log_y, base_log_y, y_min3d),
  2676.                  CheckLog(is_log_y, base_log_y, y_max3d)));
  2677.  
  2678.     /* to allow for rounding errors */
  2679.     ticmin = min(y_min3d,y_max3d) - SIGNIF*incr;
  2680.     ticmax = max(y_min3d,y_max3d) + SIGNIF*incr;
  2681.     end = end + SIGNIF*incr; 
  2682.  
  2683.     for (ticplace = start; ticplace <= end; ticplace +=incr) {
  2684.         place = (is_log_y ? log(ticplace)/log_base_log_y : ticplace);
  2685.         if ( inrange(place,ticmin,ticmax) )
  2686.          ytick3d(place, xformat, spacing, 1.0, xpos);
  2687.     }
  2688. }
  2689.  
  2690. /* DRAW_SERIES_3DZTICS: draw a user tic series, z axis */
  2691. static draw_series_3dztics(start, incr, end, xpos, ypos, z_min, z_max)
  2692.         double start, incr, end; /* tic series definition */
  2693.         double xpos, ypos, z_min, z_max;
  2694.         /* assume start < end, incr > 0 */
  2695. {
  2696.     int x, y;
  2697.     double ticplace, place;
  2698.     double ticmin, ticmax;    /* for checking if tic is almost inrange */
  2699.     double spacing = is_log_x ? log(incr)/log_base_log_x : incr;
  2700.  
  2701.     if (end == VERYLARGE)
  2702.         end = max(CheckLog(is_log_z, base_log_z, z_min),
  2703.               CheckLog(is_log_z, base_log_z, z_max));
  2704.     else
  2705.       /* limit to right side of plot */
  2706.       end = min(end, max(CheckLog(is_log_z, base_log_z, z_min),
  2707.                  CheckLog(is_log_z, base_log_z, z_max)));
  2708.  
  2709.     /* to allow for rounding errors */
  2710.     ticmin = min(z_min,z_max) - SIGNIF*incr;
  2711.     ticmax = max(z_min,z_max) + SIGNIF*incr;
  2712.     end = end + SIGNIF*incr; 
  2713.  
  2714.     for (ticplace = start; ticplace <= end; ticplace +=incr) {
  2715.         place = (is_log_z ? log(ticplace)/log_base_log_z : ticplace);
  2716.         if ( inrange(place,ticmin,ticmax) )
  2717.          ztick3d(place, zformat, spacing, 1.0, xpos, ypos);
  2718.     }
  2719.  
  2720.     /* Make sure the vertical line is fully drawn. */
  2721.     setlinestyle(-2);    /* axis line type */
  2722.  
  2723.     map3d_xy(xpos, ypos, z_min3d, &x, &y);
  2724.     clip_move(x,y);
  2725.     map3d_xy(xpos, ypos, min(end,z_max)+(is_log_z ? incr : 0.0), &x, &y);
  2726.     clip_vector(x,y);
  2727.  
  2728.     setlinestyle(-1); /* border linetype */
  2729. }
  2730. extern char *month[];
  2731. extern char *day[];
  2732. draw_month_3dxtics(ypos)
  2733. double ypos;
  2734. {
  2735.     long l_ticplace,l_incr,l_end,m_calc;
  2736.  
  2737.     l_ticplace = (long)x_min3d;
  2738.     if((double)l_ticplace<x_min3d)l_ticplace++;
  2739.     l_end=(long)x_max3d;
  2740.     l_incr=(l_end-l_ticplace)/12;
  2741.     if(l_incr<1)l_incr=1;
  2742.     while(l_ticplace<=l_end)
  2743.     {    m_calc=(l_ticplace-1)%12;
  2744.     if(m_calc<0)m_calc += 12;
  2745.     xtick3d((double)l_ticplace,month[m_calc],(double)l_incr,1.0,ypos);
  2746.     l_ticplace += l_incr;
  2747.     }
  2748. }
  2749. draw_month_3dytics(xpos)
  2750. double xpos;
  2751. {
  2752.     long l_ticplace,l_incr,l_end,m_calc;
  2753.  
  2754.     l_ticplace = (long)y_min3d;
  2755.     if((double)l_ticplace<y_min3d)l_ticplace++;
  2756.     l_end=(long)y_max3d;
  2757.     l_incr=(l_end-l_ticplace)/12;
  2758.     if(l_incr<1)l_incr=1;
  2759.     while(l_ticplace<=l_end)
  2760.     {    m_calc=(l_ticplace-1)%12;
  2761.     if(m_calc<0)m_calc += 12;
  2762.     ytick3d((double)l_ticplace,month[m_calc],(double)l_incr,1.0,xpos);
  2763.     l_ticplace += l_incr;
  2764.     }
  2765. }
  2766. draw_month_3dztics(xpos,ypos,z_min3d,z_max3d)
  2767. double xpos,ypos,z_min3d,z_max3d;
  2768. {
  2769.     long l_ticplace,l_incr,l_end,m_calc;
  2770.  
  2771.     l_ticplace = (long)z_min3d;
  2772.     if((double)l_ticplace<z_min3d)l_ticplace++;
  2773.     l_end=(long)z_max3d;
  2774.     l_incr=(l_end-l_ticplace)/12;
  2775.     if(l_incr<1)l_incr=1;
  2776.     while(l_ticplace<=l_end)
  2777.     {    m_calc=(l_ticplace-1)%12;
  2778.     if(m_calc<0)m_calc += 12;
  2779.     ztick3d((double)l_ticplace,month[m_calc],(double)l_incr,1.0,xpos,ypos);
  2780.     l_ticplace += l_incr;
  2781.     }
  2782. }
  2783. draw_day_3dxtics(ypos)
  2784. double ypos;
  2785. {
  2786.     long l_ticplace,l_incr,l_end,m_calc;
  2787.  
  2788.     l_ticplace = (long)x_min3d;
  2789.     if((double)l_ticplace<x_min3d)l_ticplace++;
  2790.     l_end=(long)x_max3d;
  2791.     l_incr=(l_end-l_ticplace)/14;
  2792.     if(l_incr<1)l_incr=1;
  2793.     while(l_ticplace<=l_end)
  2794.     {    m_calc=l_ticplace%7;
  2795.     if(m_calc<0)m_calc += 7;
  2796.     xtick3d((double)l_ticplace,day[m_calc],(double)l_incr,1.0,ypos);
  2797.     l_ticplace += l_incr;
  2798.     }
  2799. }
  2800. draw_day_3dytics(xpos)
  2801. double xpos;
  2802. {
  2803.     long l_ticplace,l_incr,l_end,m_calc;
  2804.  
  2805.     l_ticplace = (long)y_min3d;
  2806.     if((double)l_ticplace<y_min3d)l_ticplace++;
  2807.     l_end=(long)y_max3d;
  2808.     l_incr=(l_end-l_ticplace)/14;
  2809.     if(l_incr<1)l_incr=1;
  2810.     while(l_ticplace<=l_end)
  2811.     {    m_calc=l_ticplace%7;
  2812.     if(m_calc<0)m_calc += 7;
  2813.     ytick3d((double)l_ticplace,day[m_calc],(double)l_incr,1.0,xpos);
  2814.     l_ticplace += l_incr;
  2815.     }
  2816. }
  2817. draw_day_3dztics(xpos,ypos,z_min3d,z_max3d)
  2818. double xpos,ypos,z_min3d,z_max3d;
  2819. {
  2820.     long l_ticplace,l_incr,l_end,m_calc;
  2821.  
  2822.     l_ticplace = (long)z_min3d;
  2823.     if((double)l_ticplace<z_min3d)l_ticplace++;
  2824.     l_end=(long)z_max3d;
  2825.     l_incr=(l_end-l_ticplace)/14;
  2826.     if(l_incr<1)l_incr=1;
  2827.     while(l_ticplace<=l_end)
  2828.     {    m_calc=l_ticplace%7;
  2829.     if(m_calc<0)m_calc += 7;
  2830.     ztick3d((double)l_ticplace,day[m_calc],(double)l_incr,1.0,xpos,ypos);
  2831.     l_ticplace += l_incr;
  2832.     }
  2833. }
  2834. /* DRAW_SET_3DXTICS: draw a user tic set, x axis */
  2835. static draw_set_3dxtics(list, ypos)
  2836.     struct ticmark *list;    /* list of tic marks */
  2837.     double ypos;
  2838. {
  2839.     double ticplace;
  2840.     double incr = (x_max3d - x_min3d) / 10;
  2841.     /* global x_min3d, x_max3d, xscale, y_min3d, y_max3d, yscale */
  2842.  
  2843.     while (list != NULL) {
  2844.        ticplace = (is_log_x ? log(list->position)/log_base_log_x
  2845.                 : list->position);
  2846.        if ( inrange(ticplace, x_min3d, x_max3d)         /* in range */
  2847.           || NearlyEqual(ticplace, x_min3d, incr)    /* == x_min */
  2848.           || NearlyEqual(ticplace, x_max3d, incr))    /* == x_max */
  2849.         xtick3d(ticplace, list->label, incr, 1.0, ypos);
  2850.  
  2851.        list = list->next;
  2852.     }
  2853. }
  2854.  
  2855. /* DRAW_SET_3DYTICS: draw a user tic set, y axis */
  2856. static draw_set_3dytics(list, xpos)
  2857.     struct ticmark *list;    /* list of tic marks */
  2858.     double xpos;
  2859. {
  2860.     double ticplace;
  2861.     double incr = (y_max3d - y_min3d) / 10;
  2862.     /* global x_min3d, x_max3d, xscale, y_min3d, y_max3d, yscale */
  2863.  
  2864.     while (list != NULL) {
  2865.        ticplace = (is_log_y ? log(list->position)/log_base_log_y
  2866.                 : list->position);
  2867.        if ( inrange(ticplace, y_min3d, y_max3d)           /* in range */
  2868.           || NearlyEqual(ticplace, y_min3d, incr)    /* == y_min3d */
  2869.           || NearlyEqual(ticplace, y_max3d, incr))    /* == y_max3d */
  2870.         ytick3d(ticplace, list->label, incr, 1.0, xpos);
  2871.  
  2872.        list = list->next;
  2873.     }
  2874. }
  2875.  
  2876. /* DRAW_SET_3DZTICS: draw a user tic set, z axis */
  2877. static draw_set_3dztics(list, xpos, ypos, z_min, z_max)
  2878.     struct ticmark *list;    /* list of tic marks */
  2879.     double xpos, ypos, z_min, z_max;
  2880. {
  2881.     int x, y;
  2882.     double ticplace;
  2883.     double incr = (z_max - z_min) / 10;
  2884.  
  2885.     while (list != NULL) {
  2886.        ticplace = (is_log_z ? log(list->position)/log_base_log_z
  2887.                 : list->position);
  2888.        if ( inrange(ticplace, z_min, z_max)         /* in range */
  2889.           || NearlyEqual(ticplace, z_min, incr)        /* == z_min */
  2890.           || NearlyEqual(ticplace, z_max, incr))    /* == z_max */
  2891.         ztick3d(ticplace, list->label, incr, 1.0, xpos, ypos);
  2892.  
  2893.        list = list->next;
  2894.     }
  2895.  
  2896.     /* Make sure the vertical line is fully drawn. */
  2897.     setlinestyle(-2);    /* axis line type */
  2898.  
  2899.     map3d_xy(xpos, ypos, z_min, &x, &y);
  2900.     clip_move(x,y);
  2901.     map3d_xy(xpos, ypos, z_max+(is_log_z ? incr : 0.0), &x, &y);
  2902.     clip_vector(x,y);
  2903.  
  2904.     setlinestyle(-1); /* border linetype */
  2905. }
  2906.  
  2907. /* draw and label a x-axis ticmark */
  2908. #ifdef THINK_C
  2909. int xtick3d(place, text, spacing, ticscale, ypos)
  2910. #else
  2911. static xtick(place, text, spacing, ticscale, ypos)
  2912. #endif
  2913.         double place;                   /* where on axis to put it */
  2914.         char *text;                     /* optional text label */
  2915.         double spacing;         /* something to use with checkzero */
  2916.         double ticscale;         /* scale factor for tic mark (0..1] */
  2917.     double ypos;
  2918. {
  2919.     register struct termentry *t = &term_tbl[term];
  2920.     char ticlabel[101];
  2921.     int x0,y0,x1,y1,x2,y2,x3,y3;
  2922.     int ticsize = (int)((t->h_tic) * ticscale);
  2923.     double v[2], len;
  2924.  
  2925.     place = CheckZero(place,spacing); /* to fix rounding error near zero */
  2926.  
  2927.  
  2928.     if(x_max3d> x_min3d){
  2929.         if (place > x_max3d || place < x_min3d) return(0);
  2930.     }else{
  2931.         if (place > x_min3d || place < x_max3d) return(0);
  2932.     }
  2933.  
  2934.     map3d_xy(place, ypos, z_min3d, &x0, &y0);
  2935.     /* need to figure out which is in. pick the middle point along the */
  2936.     /* axis as in.                               */
  2937.     map3d_xy(place, (y_max3d + y_min3d) / 2, z_min3d, &x1, &y1);
  2938.  
  2939.     /* compute a vector of length 1 into the grid: */
  2940.     v[0] = x1 - x0;
  2941.     v[1] = y1 - y0;
  2942.     len = sqrt(v[0] * v[0] + v[1] * v[1]);
  2943.     if (len == 0.0) return;
  2944.     v[0] /= len;
  2945.     v[1] /= len;
  2946.  
  2947.     if (tic_in) {
  2948.     x1 = x0;
  2949.     y1 = y0;
  2950.     x2 = x1 + ((int) (v[0] * ticsize));
  2951.     y2 = y1 + ((int) (v[1] * ticsize));
  2952.         x3 = x0 - ((int) (v[0] * ticsize * 3)); /* compute text position */
  2953.         y3 = y0 - ((int) (v[1] * ticsize * 3));
  2954.     } else {
  2955.     x1 = x0;
  2956.     y1 = y0;
  2957.     x2 = x0 - ((int) (v[0] * ticsize));
  2958.     y2 = y0 - ((int) (v[1] * ticsize));
  2959.         x3 = x0 - ((int) (v[0] * ticsize * 4)); /* compute text position */
  2960.         y3 = y0 - ((int) (v[1] * ticsize * 4));
  2961.     }
  2962.     clip_move(x1,y1);
  2963.     clip_vector(x2,y2);
  2964.  
  2965.     /* label the ticmark */
  2966.     if (text == NULL)
  2967.      text = xformat;
  2968.  
  2969.     (void) sprintf(ticlabel, text, CheckLog(is_log_x, base_log_x, place));
  2970.     if (apx_eq(v[0], 0.0)) {
  2971.         if ((*t->justify_text)(CENTRE)) {
  2972.             clip_put_text(x3,y3,ticlabel);
  2973.         } else {
  2974.             clip_put_text(x3-(t->h_char)*strlen(ticlabel)/2,y3,ticlabel);
  2975.         }
  2976.     }
  2977.     else if (v[0] > 0) {
  2978.         if ((*t->justify_text)(RIGHT)) {
  2979.             clip_put_text(x3,y3,ticlabel);
  2980.         } else {
  2981.             clip_put_text(x3-(t->h_char)*strlen(ticlabel),y3,ticlabel);
  2982.         }
  2983.     } else {
  2984.         (*t->justify_text)(LEFT);
  2985.     clip_put_text(x3,y3,ticlabel);
  2986.     }
  2987. }
  2988.  
  2989. /* draw and label a y-axis ticmark */
  2990. #ifdef THINK_C
  2991. int ytick3d(place, text, spacing, ticscale, xpos)
  2992. #else
  2993. static ytick(place, text, spacing, ticscale, xpos)
  2994. #endif
  2995.         double place;                   /* where on axis to put it */
  2996.         char *text;                     /* optional text label */
  2997.         double spacing;         /* something to use with checkzero */
  2998.         double ticscale;         /* scale factor for tic mark (0..1] */
  2999.     double xpos;
  3000. {
  3001.     register struct termentry *t = &term_tbl[term];
  3002.     char ticlabel[101];
  3003.     int x0,y0,x1,y1,x2,y2,x3,y3;
  3004.     int ticsize = (int)((t->h_tic) * ticscale);
  3005.     double v[2], len;
  3006.  
  3007.     place = CheckZero(place,spacing); /* to fix rounding error near zero */
  3008.  
  3009.     if(y_max3d> y_min3d){
  3010.         if (place > y_max3d || place < y_min3d) return(0);
  3011.     }else{
  3012.         if (place > y_min3d || place < y_max3d) return(0);
  3013.     }
  3014.  
  3015.     map3d_xy(xpos, place, z_min3d, &x0, &y0);
  3016.     /* need to figure out which is in. pick the middle point along the */
  3017.     /* axis as in.                               */
  3018.     map3d_xy((x_max3d + x_min3d) / 2, place, z_min3d, &x1, &y1);
  3019.  
  3020.     /* compute a vector of length 1 into the grid: */
  3021.     v[0] = x1 - x0;
  3022.     v[1] = y1 - y0;
  3023.     len = sqrt(v[0] * v[0] + v[1] * v[1]);
  3024.     if (len == 0.0) return(0);
  3025.     v[0] /= len;
  3026.     v[1] /= len;
  3027.  
  3028.     if (tic_in) {
  3029.     x1 = x0;
  3030.     y1 = y0;
  3031.     x2 = x1 + ((int) (v[0] * ticsize));
  3032.     y2 = y1 + ((int) (v[1] * ticsize));
  3033.         x3 = x0 - ((int) (v[0] * ticsize * 3)); /* compute text position */
  3034.         y3 = y0 - ((int) (v[1] * ticsize * 3));
  3035.     } else {
  3036.     x1 = x0;
  3037.     y1 = y0;
  3038.     x2 = x0 - ((int) (v[0] * ticsize));
  3039.     y2 = y0 - ((int) (v[1] * ticsize));
  3040.         x3 = x0 - ((int) (v[0] * ticsize * 4)); /* compute text position */
  3041.         y3 = y0 - ((int) (v[1] * ticsize * 4));
  3042.     }
  3043.     clip_move(x1,y1);
  3044.     clip_vector(x2,y2);
  3045.  
  3046.     /* label the ticmark */
  3047.     if (text == NULL)
  3048.      text = yformat;
  3049.  
  3050.     (void) sprintf(ticlabel, text, CheckLog(is_log_y, base_log_y, place));
  3051.     if (apx_eq(v[0], 0.0)) {
  3052.         if ((*t->justify_text)(CENTRE)) {
  3053.             clip_put_text(x3,y3,ticlabel);
  3054.         } else {
  3055.             clip_put_text(x3-(t->h_char)*strlen(ticlabel)/2,y3,ticlabel);
  3056.         }
  3057.     }
  3058.     else if (v[0] > 0) {
  3059.         if ((*t->justify_text)(RIGHT)) {
  3060.             clip_put_text(x3,y3,ticlabel);
  3061.         } else {
  3062.             clip_put_text(x3-(t->h_char)*strlen(ticlabel),y3,ticlabel);
  3063.         }
  3064.     } else {
  3065.         (*t->justify_text)(LEFT);
  3066.     clip_put_text(x3,y3,ticlabel);
  3067.     }
  3068. }
  3069.  
  3070. /* draw and label a z-axis ticmark */
  3071. #ifdef THINK_C
  3072. int ztick3d(place, text, spacing, ticscale, xpos, ypos)
  3073. #else
  3074. static ztick(place, text, spacing, ticscale, xpos, ypos)
  3075. #endif
  3076.         double place;                   /* where on axis to put it */
  3077.         char *text;                     /* optional text label */
  3078.         double spacing;         /* something to use with checkzero */
  3079.         double ticscale;         /* scale factor for tic mark (0..1] */
  3080.     double xpos, ypos;
  3081. {
  3082.     register struct termentry *t = &term_tbl[term];
  3083.     char ticlabel[101];
  3084.     int x0,y0,x1,y1,x2,y2,x3,y3;
  3085.     int ticsize = (int)((t->h_tic) * ticscale);
  3086.  
  3087.     place = CheckZero(place,spacing); /* to fix rounding error near zero */
  3088.  
  3089.     map3d_xy(xpos, ypos, place, &x0, &y0);
  3090.  
  3091.     if (tic_in) {
  3092.     x1 = x0;
  3093.     y1 = y0;
  3094.     x2 = x0 + ticsize;
  3095.     y2 = y0;
  3096.         x3 = x0 - ticsize;
  3097.         y3 = y0;
  3098.     } else {
  3099.     x1 = x0;
  3100.     y1 = y0;
  3101.     x2 = x0 - ticsize;
  3102.     y2 = y0;
  3103.         x3 = x0 - ticsize * 2; /* compute text position */
  3104.         y3 = y0;
  3105.     }
  3106.     clip_move(x1,y1);
  3107.     clip_vector(x2,y2);
  3108.  
  3109.     /* label the ticmark */
  3110.     if (text == NULL)
  3111.      text = zformat;
  3112.  
  3113.     (void) sprintf(ticlabel, text, CheckLog(is_log_z, base_log_z, place));
  3114.     if ((*t->justify_text)(RIGHT)) {
  3115.         clip_put_text(x3,y3,ticlabel);
  3116.     } else {
  3117.         clip_put_text(x3-(t->h_char)*(strlen(ticlabel)+1),y3,ticlabel);
  3118.     }
  3119. }
  3120.  
  3121. #endif /* THINK_C_4 */
  3122.